summaryrefslogtreecommitdiff
path: root/chromium/content/browser
diff options
context:
space:
mode:
authorAndras Becsi <andras.becsi@digia.com>2013-12-11 21:33:03 +0100
committerAndras Becsi <andras.becsi@digia.com>2013-12-13 12:34:07 +0100
commitf2a33ff9cbc6d19943f1c7fbddd1f23d23975577 (patch)
tree0586a32aa390ade8557dfd6b4897f43a07449578 /chromium/content/browser
parent5362912cdb5eea702b68ebe23702468d17c3017a (diff)
downloadqtwebengine-chromium-f2a33ff9cbc6d19943f1c7fbddd1f23d23975577.tar.gz
Update Chromium to branch 1650 (31.0.1650.63)
Change-Id: I57d8c832eaec1eb2364e0a8e7352a6dd354db99f Reviewed-by: Jocelyn Turcotte <jocelyn.turcotte@digia.com>
Diffstat (limited to 'chromium/content/browser')
-rw-r--r--chromium/content/browser/DEPS7
-rw-r--r--chromium/content/browser/accessibility/accessibility_ui.cc12
-rw-r--r--chromium/content/browser/accessibility/accessibility_win_browsertest.cc20
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility.cc231
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility.h134
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_android.cc124
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_cocoa.h4
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_cocoa.mm627
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_gtk.cc52
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_gtk.h4
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm11
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager.cc50
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager.h15
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_android.cc28
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_android.h4
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_gtk.cc12
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_gtk.h4
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_mac.h4
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm73
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc116
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_win.cc57
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_win.h4
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_state_impl.cc13
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_win.cc598
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_win.h8
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc181
-rw-r--r--chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc160
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc8
-rw-r--r--chromium/content/browser/android/OWNERS3
-rw-r--r--chromium/content/browser/android/android_browser_process.cc47
-rw-r--r--chromium/content/browser/android/android_browser_process.h16
-rw-r--r--chromium/content/browser/android/browser_jni_registrar.cc83
-rw-r--r--chromium/content/browser/android/browser_jni_registrar.h21
-rw-r--r--chromium/content/browser/android/browser_startup_config.cc25
-rw-r--r--chromium/content/browser/android/browser_startup_controller.cc56
-rw-r--r--chromium/content/browser/android/browser_startup_controller.h (renamed from chromium/content/browser/android/browser_startup_config.h)8
-rw-r--r--chromium/content/browser/android/child_process_launcher_android.cc2
-rw-r--r--chromium/content/browser/android/content_startup_flags.cc3
-rw-r--r--chromium/content/browser/android/content_video_view.cc2
-rw-r--r--chromium/content/browser/android/content_view_core_impl.cc97
-rw-r--r--chromium/content/browser/android/content_view_core_impl.h24
-rw-r--r--chromium/content/browser/android/content_view_render_view.cc48
-rw-r--r--chromium/content/browser/android/content_view_render_view.h29
-rw-r--r--chromium/content/browser/android/date_time_chooser_android.cc72
-rw-r--r--chromium/content/browser/android/date_time_chooser_android.h29
-rw-r--r--chromium/content/browser/android/in_process/synchronous_compositor_impl.cc189
-rw-r--r--chromium/content/browser/android/in_process/synchronous_compositor_impl.h5
-rw-r--r--chromium/content/browser/android/in_process/synchronous_compositor_output_surface.cc115
-rw-r--r--chromium/content/browser/android/in_process/synchronous_compositor_output_surface.h19
-rw-r--r--chromium/content/browser/android/in_process/synchronous_input_event_filter.cc2
-rw-r--r--chromium/content/browser/android/overscroll_glow.cc7
-rw-r--r--chromium/content/browser/android/overscroll_glow.h7
-rw-r--r--chromium/content/browser/android/surface_texture_peer_browser_impl.cc12
-rw-r--r--chromium/content/browser/android/surface_texture_peer_browser_impl.h2
-rw-r--r--chromium/content/browser/android/tracing_intent_handler.cc2
-rw-r--r--chromium/content/browser/android/web_contents_observer_android.cc22
-rw-r--r--chromium/content/browser/android/web_contents_observer_android.h2
-rw-r--r--chromium/content/browser/aura/browser_compositor_output_surface.cc14
-rw-r--r--chromium/content/browser/aura/browser_compositor_output_surface.h4
-rw-r--r--chromium/content/browser/aura/compositor_resize_lock.cc65
-rw-r--r--chromium/content/browser/aura/compositor_resize_lock.h46
-rw-r--r--chromium/content/browser/aura/gpu_process_transport_factory.cc70
-rw-r--r--chromium/content/browser/aura/gpu_process_transport_factory.h14
-rw-r--r--chromium/content/browser/aura/image_transport_factory.cc7
-rw-r--r--chromium/content/browser/aura/image_transport_factory.h11
-rw-r--r--chromium/content/browser/aura/no_transport_image_transport_factory.cc48
-rw-r--r--chromium/content/browser/aura/no_transport_image_transport_factory.h6
-rw-r--r--chromium/content/browser/aura/reflector_impl.cc3
-rw-r--r--chromium/content/browser/aura/resize_lock.cc35
-rw-r--r--chromium/content/browser/aura/resize_lock.h37
-rw-r--r--chromium/content/browser/aura/software_browser_compositor_output_surface.cc2
-rw-r--r--chromium/content/browser/aura/software_output_device_win.cc22
-rw-r--r--chromium/content/browser/aura/software_output_device_win.h1
-rw-r--r--chromium/content/browser/aura/software_output_device_x11.cc2
-rw-r--r--chromium/content/browser/aura/software_output_device_x11.h4
-rw-r--r--chromium/content/browser/bookmarklet_browsertest.cc2
-rw-r--r--chromium/content/browser/browser_child_process_host_impl.cc12
-rw-r--r--chromium/content/browser/browser_child_process_host_impl.h5
-rw-r--r--chromium/content/browser/browser_main_loop.cc203
-rw-r--r--chromium/content/browser/browser_main_loop.h16
-rw-r--r--chromium/content/browser/browser_main_runner.cc132
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_embedder.cc3
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_guest.cc162
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_guest.h26
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_guest_manager.cc2
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_host_browsertest.cc186
-rw-r--r--chromium/content/browser/browser_plugin/test_browser_plugin_guest_delegate.cc66
-rw-r--r--chromium/content/browser/browser_plugin/test_browser_plugin_guest_delegate.h51
-rw-r--r--chromium/content/browser/browser_shutdown_profile_dumper.cc139
-rw-r--r--chromium/content/browser/browser_shutdown_profile_dumper.h74
-rw-r--r--chromium/content/browser/browser_thread_impl.h1
-rw-r--r--chromium/content/browser/browser_url_handler_impl.cc5
-rw-r--r--chromium/content/browser/byte_stream.cc31
-rw-r--r--chromium/content/browser/byte_stream.h4
-rw-r--r--chromium/content/browser/byte_stream_unittest.cc31
-rw-r--r--chromium/content/browser/child_process_launcher.cc16
-rw-r--r--chromium/content/browser/child_process_launcher.h7
-rw-r--r--chromium/content/browser/child_process_security_policy_browsertest.cc2
-rw-r--r--chromium/content/browser/child_process_security_policy_impl.cc54
-rw-r--r--chromium/content/browser/child_process_security_policy_impl.h35
-rw-r--r--chromium/content/browser/child_process_security_policy_unittest.cc6
-rw-r--r--chromium/content/browser/database_browsertest.cc2
-rw-r--r--chromium/content/browser/device_orientation/data_fetcher_impl_android.cc127
-rw-r--r--chromium/content/browser/device_orientation/data_fetcher_impl_android.h19
-rw-r--r--chromium/content/browser/device_orientation/data_fetcher_impl_android_unittest.cc87
-rw-r--r--chromium/content/browser/device_orientation/data_fetcher_shared_memory.h77
-rw-r--r--chromium/content/browser/device_orientation/data_fetcher_shared_memory_android.cc55
-rw-r--r--chromium/content/browser/device_orientation/data_fetcher_shared_memory_base.cc247
-rw-r--r--chromium/content/browser/device_orientation/data_fetcher_shared_memory_base.h90
-rw-r--r--chromium/content/browser/device_orientation/data_fetcher_shared_memory_base_unittest.cc407
-rw-r--r--chromium/content/browser/device_orientation/data_fetcher_shared_memory_default.cc73
-rw-r--r--chromium/content/browser/device_orientation/data_fetcher_shared_memory_mac.cc166
-rw-r--r--chromium/content/browser/device_orientation/data_fetcher_shared_memory_win.cc394
-rw-r--r--chromium/content/browser/device_orientation/device_inertial_sensor_service.cc94
-rw-r--r--chromium/content/browser/device_orientation/device_inertial_sensor_service.h (renamed from chromium/content/browser/device_orientation/device_motion_service.h)41
-rw-r--r--chromium/content/browser/device_orientation/device_motion_message_filter.cc16
-rw-r--r--chromium/content/browser/device_orientation/device_motion_provider.cc172
-rw-r--r--chromium/content/browser/device_orientation/device_motion_provider.h56
-rw-r--r--chromium/content/browser/device_orientation/device_motion_provider_unittest.cc98
-rw-r--r--chromium/content/browser/device_orientation/device_motion_service.cc65
-rw-r--r--chromium/content/browser/device_orientation/device_orientation_browsertest.cc4
-rw-r--r--chromium/content/browser/device_orientation/device_orientation_message_filter.cc30
-rw-r--r--chromium/content/browser/device_orientation/inertial_sensor_consts.h19
-rw-r--r--chromium/content/browser/devtools/browser_protocol.json48
-rw-r--r--chromium/content/browser/devtools/devtools_frontend_host.cc86
-rw-r--r--chromium/content/browser/devtools/devtools_frontend_host.h17
-rw-r--r--chromium/content/browser/devtools/devtools_http_handler_impl.cc7
-rw-r--r--chromium/content/browser/devtools/devtools_http_handler_unittest.cc10
-rw-r--r--chromium/content/browser/devtools/devtools_protocol.cc5
-rw-r--r--chromium/content/browser/devtools/devtools_protocol.h2
-rw-r--r--chromium/content/browser/devtools/devtools_protocol_constants.cc113
-rw-r--r--chromium/content/browser/devtools/devtools_protocol_constants.h192
-rw-r--r--chromium/content/browser/devtools/devtools_system_info_handler.cc123
-rw-r--r--chromium/content/browser/devtools/devtools_system_info_handler.h28
-rw-r--r--chromium/content/browser/devtools/render_view_devtools_agent_host.cc65
-rw-r--r--chromium/content/browser/devtools/render_view_devtools_agent_host.h15
-rw-r--r--chromium/content/browser/devtools/renderer_overrides_handler.cc513
-rw-r--r--chromium/content/browser/devtools/renderer_overrides_handler.h43
-rw-r--r--chromium/content/browser/devtools/tethering_handler.cc8
-rw-r--r--chromium/content/browser/devtools/worker_devtools_manager.cc18
-rw-r--r--chromium/content/browser/devtools/worker_devtools_manager.h5
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_browsertest.cc5
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_host.cc24
-rw-r--r--chromium/content/browser/dom_storage/session_storage_database.cc2
-rw-r--r--chromium/content/browser/dom_storage/session_storage_database_unittest.cc1
-rw-r--r--chromium/content/browser/download/base_file_unittest.cc2
-rw-r--r--chromium/content/browser/download/download_browsertest.cc50
-rw-r--r--chromium/content/browser/download/download_file_unittest.cc8
-rw-r--r--chromium/content/browser/download/download_manager_impl_unittest.cc3
-rw-r--r--chromium/content/browser/download/download_resource_handler.cc3
-rw-r--r--chromium/content/browser/download/download_resource_handler.h1
-rw-r--r--chromium/content/browser/download/drag_download_file_browsertest.cc6
-rw-r--r--chromium/content/browser/download/file_metadata_mac.mm2
-rw-r--r--chromium/content/browser/download/file_metadata_unittest_linux.cc3
-rw-r--r--chromium/content/browser/download/mhtml_generation_browsertest.cc4
-rw-r--r--chromium/content/browser/download/mhtml_generation_manager.cc77
-rw-r--r--chromium/content/browser/download/mhtml_generation_manager.h27
-rw-r--r--chromium/content/browser/download/save_package.cc12
-rw-r--r--chromium/content/browser/download/save_package.h2
-rw-r--r--chromium/content/browser/download/save_package_browsertest.cc2
-rw-r--r--chromium/content/browser/download/save_package_unittest.cc2
-rw-r--r--chromium/content/browser/fileapi/browser_file_system_helper.cc21
-rw-r--r--chromium/content/browser/fileapi/browser_file_system_helper.h8
-rw-r--r--chromium/content/browser/fileapi/chrome_blob_storage_context.cc6
-rw-r--r--chromium/content/browser/fileapi/chrome_blob_storage_context.h8
-rw-r--r--chromium/content/browser/fileapi/file_system_browsertest.cc5
-rw-r--r--chromium/content/browser/fileapi/fileapi_message_filter.cc351
-rw-r--r--chromium/content/browser/fileapi/fileapi_message_filter.h67
-rw-r--r--chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc37
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc14
-rw-r--r--chromium/content/browser/geolocation/core_location_data_provider_mac.h54
-rw-r--r--chromium/content/browser/geolocation/core_location_data_provider_mac.mm256
-rw-r--r--chromium/content/browser/geolocation/core_location_provider_mac.h40
-rw-r--r--chromium/content/browser/geolocation/core_location_provider_mac.mm68
-rw-r--r--chromium/content/browser/geolocation/device_data_provider.h305
-rw-r--r--chromium/content/browser/geolocation/device_data_provider_unittest.cc41
-rw-r--r--chromium/content/browser/geolocation/empty_device_data_provider.cc18
-rw-r--r--chromium/content/browser/geolocation/empty_device_data_provider.h36
-rw-r--r--chromium/content/browser/geolocation/empty_wifi_data_provider.cc29
-rw-r--r--chromium/content/browser/geolocation/empty_wifi_data_provider.h31
-rw-r--r--chromium/content/browser/geolocation/geolocation_dispatcher_host.cc38
-rw-r--r--chromium/content/browser/geolocation/geolocation_provider_impl.cc6
-rw-r--r--chromium/content/browser/geolocation/geolocation_provider_impl.h16
-rw-r--r--chromium/content/browser/geolocation/geolocation_provider_unittest.cc10
-rw-r--r--chromium/content/browser/geolocation/location_arbitrator.h4
-rw-r--r--chromium/content/browser/geolocation/location_arbitrator_impl.cc42
-rw-r--r--chromium/content/browser/geolocation/location_arbitrator_impl.h11
-rw-r--r--chromium/content/browser/geolocation/location_arbitrator_impl_unittest.cc16
-rw-r--r--chromium/content/browser/geolocation/mock_location_arbitrator.cc10
-rw-r--r--chromium/content/browser/geolocation/mock_location_arbitrator.h8
-rw-r--r--chromium/content/browser/geolocation/mock_location_provider.h2
-rw-r--r--chromium/content/browser/geolocation/network_location_provider.cc68
-rw-r--r--chromium/content/browser/geolocation/network_location_provider.h47
-rw-r--r--chromium/content/browser/geolocation/network_location_provider_unittest.cc64
-rw-r--r--chromium/content/browser/geolocation/network_location_request.cc16
-rw-r--r--chromium/content/browser/geolocation/network_location_request.h31
-rw-r--r--chromium/content/browser/geolocation/wifi_data.cc (renamed from chromium/content/browser/geolocation/device_data_provider.cc)14
-rw-r--r--chromium/content/browser/geolocation/wifi_data.h54
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider.cc147
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider.h162
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_chromeos.cc31
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_chromeos.h11
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_chromeos_unittest.cc2
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_common.cc51
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_common.h77
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_common_unittest.cc57
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_common_win.cc1
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_common_win.h2
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_linux.cc11
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_linux.h2
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_mac.cc11
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_mac.h2
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_win.cc11
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_win.h3
-rw-r--r--chromium/content/browser/geolocation/wifi_polling_policy.h55
-rw-r--r--chromium/content/browser/gpu/compositor_util.cc102
-rw-r--r--chromium/content/browser/gpu/compositor_util.h26
-rw-r--r--chromium/content/browser/gpu/compositor_util_browsertest.cc41
-rw-r--r--chromium/content/browser/gpu/gpu_crash_browsertest.cc2
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl.cc15
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl.h5
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl_private.cc62
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl_private.h1
-rw-r--r--chromium/content/browser/gpu/gpu_functional_browsertest.cc3
-rw-r--r--chromium/content/browser/gpu/gpu_internals_ui.cc2
-rw-r--r--chromium/content/browser/gpu/gpu_memory_test.cc12
-rw-r--r--chromium/content/browser/gpu/gpu_pixel_browsertest.cc10
-rw-r--r--chromium/content/browser/gpu/gpu_process_host.cc104
-rw-r--r--chromium/content/browser/gpu/gpu_process_host.h9
-rw-r--r--chromium/content/browser/gpu/webgl_conformance_test.cc2
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store.cc82
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store.h5
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store_unittest.cc49
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_browsertest.cc17
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc7
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_context_impl.cc38
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_cursor.cc128
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_cursor.h15
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database.cc1011
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database.h76
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc19
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h7
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory.cc89
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory.h8
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_internals_ui.cc5
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc391
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h4
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc3
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_quota_client.cc4
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_quota_client.h1
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_transaction.cc61
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_transaction.h60
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.cc74
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.h3
-rw-r--r--chromium/content/browser/indexed_db/leveldb/avltree.h977
-rw-r--r--chromium/content/browser/indexed_db/leveldb/fixed_array.h63
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_database.cc15
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_database.h1
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_transaction.cc272
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_transaction.h81
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_unittest.cc46
-rw-r--r--chromium/content/browser/indexed_db/list_set.h2
-rw-r--r--chromium/content/browser/loader/async_resource_handler.cc44
-rw-r--r--chromium/content/browser/loader/async_resource_handler.h5
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc6
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_impl.cc115
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_impl.h7
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_unittest.cc52
-rw-r--r--chromium/content/browser/loader/resource_message_filter.cc17
-rw-r--r--chromium/content/browser/loader/resource_message_filter.h42
-rw-r--r--chromium/content/browser/loader/resource_request_info_impl.cc9
-rw-r--r--chromium/content/browser/loader/resource_request_info_impl.h12
-rw-r--r--chromium/content/browser/loader/resource_scheduler.cc3
-rw-r--r--chromium/content/browser/loader/resource_scheduler_unittest.cc34
-rw-r--r--chromium/content/browser/loader/sync_resource_handler.cc9
-rw-r--r--chromium/content/browser/loader/sync_resource_handler.h3
-rw-r--r--chromium/content/browser/loader/upload_data_stream_builder.cc52
-rw-r--r--chromium/content/browser/loader/upload_data_stream_builder.h6
-rw-r--r--chromium/content/browser/loader/upload_data_stream_builder_unittest.cc57
-rw-r--r--chromium/content/browser/media/android/OWNERS1
-rw-r--r--chromium/content/browser/media/android/browser_demuxer_android.cc111
-rw-r--r--chromium/content/browser/media/android/browser_demuxer_android.h61
-rw-r--r--chromium/content/browser/media/android/browser_media_player_manager.cc (renamed from chromium/content/browser/android/browser_media_player_manager.cc)255
-rw-r--r--chromium/content/browser/media/android/browser_media_player_manager.h (renamed from chromium/content/browser/android/browser_media_player_manager.h)84
-rw-r--r--chromium/content/browser/media/android/media_drm_credential_manager.cc109
-rw-r--r--chromium/content/browser/media/android/media_drm_credential_manager.h60
-rw-r--r--chromium/content/browser/media/android/media_resource_getter_impl.cc (renamed from chromium/content/browser/android/media_resource_getter_impl.cc)4
-rw-r--r--chromium/content/browser/media/android/media_resource_getter_impl.h (renamed from chromium/content/browser/android/media_resource_getter_impl.h)8
-rw-r--r--chromium/content/browser/media/encrypted_media_browsertest.cc190
-rw-r--r--chromium/content/browser/media/media_browsertest.cc28
-rw-r--r--chromium/content/browser/media/media_browsertest.h17
-rw-r--r--chromium/content/browser/media/media_internals.cc90
-rw-r--r--chromium/content/browser/media/media_internals.h23
-rw-r--r--chromium/content/browser/media/media_internals_handler.cc2
-rw-r--r--chromium/content/browser/media/media_internals_ui.cc6
-rw-r--r--chromium/content/browser/media/media_internals_unittest.cc43
-rw-r--r--chromium/content/browser/media/webrtc_browsertest.cc118
-rw-r--r--chromium/content/browser/media/webrtc_internals.cc14
-rw-r--r--chromium/content/browser/media/webrtc_internals_browsertest.cc42
-rw-r--r--chromium/content/browser/mime_registry_message_filter.cc7
-rw-r--r--chromium/content/browser/mime_registry_message_filter.h3
-rw-r--r--chromium/content/browser/net/sqlite_persistent_cookie_store.cc8
-rw-r--r--chromium/content/browser/net/sqlite_persistent_cookie_store_perftest.cc6
-rw-r--r--chromium/content/browser/net/view_blob_internals_job_factory.cc4
-rw-r--r--chromium/content/browser/net/view_blob_internals_job_factory.h4
-rw-r--r--chromium/content/browser/notification_service_impl.cc2
-rw-r--r--chromium/content/browser/plugin_browsertest.cc2
-rw-r--r--chromium/content/browser/plugin_data_remover_impl_browsertest.cc2
-rw-r--r--chromium/content/browser/plugin_process_host.cc51
-rw-r--r--chromium/content/browser/plugin_process_host.h21
-rw-r--r--chromium/content/browser/plugin_service_impl.cc17
-rw-r--r--chromium/content/browser/plugin_service_impl.h3
-rw-r--r--chromium/content/browser/plugin_service_impl_browsertest.cc2
-rw-r--r--chromium/content/browser/power_monitor_message_broadcaster.cc2
-rw-r--r--chromium/content/browser/power_monitor_message_broadcaster.h2
-rw-r--r--chromium/content/browser/power_save_blocker_chromeos.cc9
-rw-r--r--chromium/content/browser/power_save_blocker_x11.cc5
-rw-r--r--chromium/content/browser/ppapi_plugin_process_host.cc19
-rw-r--r--chromium/content/browser/ppapi_plugin_process_host.h10
-rw-r--r--chromium/content/browser/renderer_host/DEPS4
-rw-r--r--chromium/content/browser/renderer_host/backing_store_gtk.cc22
-rw-r--r--chromium/content/browser/renderer_host/backing_store_gtk.h6
-rw-r--r--chromium/content/browser/renderer_host/backing_store_win.cc9
-rw-r--r--chromium/content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.cc4
-rw-r--r--chromium/content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.h8
-rw-r--r--chromium/content/browser/renderer_host/clipboard_message_filter.cc13
-rw-r--r--chromium/content/browser/renderer_host/compositing_iosurface_mac.h2
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android.cc147
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android.h10
-rw-r--r--chromium/content/browser/renderer_host/frame_memory_manager.cc66
-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/gtk_im_context_wrapper.cc8
-rw-r--r--chromium/content/browser/renderer_host/gtk_plugin_container_manager.cc2
-rw-r--r--chromium/content/browser/renderer_host/gtk_window_utils.cc7
-rw-r--r--chromium/content/browser/renderer_host/image_transport_factory_android.cc4
-rw-r--r--chromium/content/browser/renderer_host/ime_adapter_android.cc4
-rw-r--r--chromium/content/browser/renderer_host/input/OWNERS3
-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/immediate_input_router.cc93
-rw-r--r--chromium/content/browser/renderer_host/input/immediate_input_router.h20
-rw-r--r--chromium/content/browser/renderer_host/input/immediate_input_router_unittest.cc666
-rw-r--r--chromium/content/browser/renderer_host/input/input_ack_handler.h41
-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.h9
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_client.h19
-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.cc77
-rw-r--r--chromium/content/browser/renderer_host/input/mock_input_ack_handler.h77
-rw-r--r--chromium/content/browser/renderer_host/input/mock_input_router_client.cc148
-rw-r--r--chromium/content/browser/renderer_host/input/mock_input_router_client.h126
-rw-r--r--chromium/content/browser/renderer_host/input/touch_event_queue.cc7
-rw-r--r--chromium/content/browser/renderer_host/input/touch_event_queue.h9
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_android.cc4
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_gtk.cc603
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_gtk.h44
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_gtk_unittest.cc171
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_util.h2
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_util_posix.h2
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_device_manager.cc32
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc3
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc30
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_renderer_host.h13
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_sync_writer.cc7
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_sync_writer.h5
-rw-r--r--chromium/content/browser/renderer_host/media/audio_renderer_host.cc27
-rw-r--r--chromium/content/browser/renderer_host/media/audio_renderer_host_unittest.cc2
-rw-r--r--chromium/content/browser/renderer_host/media/desktop_capture_device.cc251
-rw-r--r--chromium/content/browser/renderer_host/media/desktop_capture_device.h2
-rw-r--r--chromium/content/browser/renderer_host/media/desktop_capture_device_unittest.cc96
-rw-r--r--chromium/content/browser/renderer_host/media/device_request_message_filter.cc9
-rw-r--r--chromium/content/browser/renderer_host/media/device_request_message_filter.h6
-rw-r--r--chromium/content/browser/renderer_host/media/device_request_message_filter_unittest.cc16
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc10
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager.cc8
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc1
-rw-r--r--chromium/content/browser/renderer_host/media/midi_dispatcher_host.cc3
-rw-r--r--chromium/content/browser/renderer_host/media/midi_host.cc55
-rw-r--r--chromium/content/browser/renderer_host/media/midi_host.h10
-rw-r--r--chromium/content/browser/renderer_host/media/mock_media_observer.h5
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_buffer_pool.cc7
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc4
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller.cc604
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller.h157
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h2
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller_unittest.cc567
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_host.cc72
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_host.h16
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_host_unittest.cc48
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager.cc635
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager.h217
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc136
-rw-r--r--chromium/content/browser/renderer_host/media/web_contents_video_capture_device.cc8
-rw-r--r--chromium/content/browser/renderer_host/media/web_contents_video_capture_device.h4
-rw-r--r--chromium/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc30
-rw-r--r--chromium/content/browser/renderer_host/media/webrtc_identity_service_host.cc27
-rw-r--r--chromium/content/browser/renderer_host/media/webrtc_identity_service_host.h15
-rw-r--r--chromium/content/browser/renderer_host/media/webrtc_identity_service_host_unittest.cc19
-rw-r--r--chromium/content/browser/renderer_host/native_web_keyboard_event.cc2
-rw-r--r--chromium/content/browser/renderer_host/native_web_keyboard_event_aura.cc5
-rw-r--r--chromium/content/browser/renderer_host/native_web_keyboard_event_gtk.cc12
-rw-r--r--chromium/content/browser/renderer_host/overscroll_configuration.cc18
-rw-r--r--chromium/content/browser/renderer_host/overscroll_controller.cc65
-rw-r--r--chromium/content/browser/renderer_host/overscroll_controller.h13
-rw-r--r--chromium/content/browser/renderer_host/p2p/OWNERS3
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc8
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h2
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host.cc9
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host.h17
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc34
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp.h4
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_throttler.cc45
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_throttler.h40
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_udp.cc14
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_udp.h6
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc76
-rw-r--r--chromium/content/browser/renderer_host/pepper/OWNERS1
-rw-r--r--chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc21
-rw-r--r--chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h13
-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.cc64
-rw-r--r--chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h26
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc13
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.h4
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.cc16
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.h6
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc38
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.h6
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc3
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc23
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.h4
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_lookup_request.h18
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_message_filter.cc459
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_message_filter.h194
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.cc121
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.h50
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc2
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.cc93
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.h12
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_security_helper.cc52
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_security_helper.h10
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_socket_utils.cc62
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_socket_utils.h27
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc100
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h35
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_tcp_socket.cc16
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_tcp_socket.h148
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc979
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h223
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc6
-rw-r--r--chromium/content/browser/renderer_host/pepper/ssl_context_helper.cc30
-rw-r--r--chromium/content/browser/renderer_host/pepper/ssl_context_helper.h48
-rw-r--r--chromium/content/browser/renderer_host/render_frame_host_impl.cc49
-rw-r--r--chromium/content/browser/renderer_host/render_frame_host_impl.h18
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_browsertest.cc2
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_impl.cc247
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_impl.h15
-rw-r--r--chromium/content/browser/renderer_host/render_sandbox_host_linux.cc11
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_browsertest.cc2
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_delegate.h17
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_factory.cc5
-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.cc104
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_impl.h44
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_manager_browsertest.cc52
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_unittest.cc7
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_browsertest.cc10
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_impl.cc232
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_impl.h76
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_unittest.cc127
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_android.cc82
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_android.h22
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura.cc578
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura.h102
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc278
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base.cc30
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base.h11
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_browsertest.cc53
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_gtk.cc56
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_gtk.h12
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_guest.cc24
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_guest.h18
-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.h26
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac.mm75
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm2
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm150
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_win.cc161
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_win.h24
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_win_browsertest.cc14
-rw-r--r--chromium/content/browser/renderer_host/smooth_scroll_calculator.cc28
-rw-r--r--chromium/content/browser/renderer_host/smooth_scroll_calculator.h29
-rw-r--r--chromium/content/browser/renderer_host/smooth_scroll_gesture_controller.cc61
-rw-r--r--chromium/content/browser/renderer_host/smooth_scroll_gesture_controller.h52
-rw-r--r--chromium/content/browser/renderer_host/socket_stream_dispatcher_host.cc8
-rw-r--r--chromium/content/browser/renderer_host/socket_stream_dispatcher_host.h9
-rw-r--r--chromium/content/browser/renderer_host/surface_texture_transport_client_android.cc8
-rw-r--r--chromium/content/browser/renderer_host/surface_texture_transport_client_android.h4
-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.cc (renamed from chromium/content/browser/renderer_host/smooth_scroll_gesture_controller_unittest.cc)34
-rw-r--r--chromium/content/browser/renderer_host/test_render_view_host.cc14
-rw-r--r--chromium/content/browser/renderer_host/test_render_view_host.h15
-rw-r--r--chromium/content/browser/renderer_host/text_input_client_mac.mm4
-rw-r--r--chromium/content/browser/renderer_host/text_input_client_mac_unittest.mm2
-rw-r--r--chromium/content/browser/renderer_host/text_input_client_message_filter.h5
-rw-r--r--chromium/content/browser/renderer_host/text_input_client_message_filter.mm2
-rw-r--r--chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_android.cc75
-rw-r--r--chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_android.h52
-rw-r--r--chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_aura.cc8
-rw-r--r--chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_aura.h8
-rw-r--r--chromium/content/browser/renderer_host/ui_events_helper.cc4
-rw-r--r--chromium/content/browser/renderer_host/web_input_event_aura.cc147
-rw-r--r--chromium/content/browser/renderer_host/web_input_event_aura.h4
-rw-r--r--chromium/content/browser/renderer_host/web_input_event_aura_unittest.cc7
-rw-r--r--chromium/content/browser/renderer_host/web_input_event_aurax11.cc106
-rw-r--r--chromium/content/browser/resources/indexed_db/indexeddb_internals.css49
-rw-r--r--chromium/content/browser/resources/indexed_db/indexeddb_internals.html89
-rw-r--r--chromium/content/browser/resources/media/cache_entry.js14
-rw-r--r--chromium/content/browser/resources/media/client_renderer.js306
-rw-r--r--chromium/content/browser/resources/media/event_list.js64
-rw-r--r--chromium/content/browser/resources/media/item_store.js70
-rw-r--r--chromium/content/browser/resources/media/main.js195
-rw-r--r--chromium/content/browser/resources/media/manager.js114
-rw-r--r--chromium/content/browser/resources/media/media_internals.css125
-rw-r--r--chromium/content/browser/resources/media/media_internals.html75
-rw-r--r--chromium/content/browser/resources/media/media_internals.js284
-rw-r--r--chromium/content/browser/resources/media/media_player.js154
-rw-r--r--chromium/content/browser/resources/media/metrics.js116
-rw-r--r--chromium/content/browser/resources/media/new/integration_test.html86
-rw-r--r--chromium/content/browser/resources/media/new/main.js134
-rw-r--r--chromium/content/browser/resources/media/new/media_internals.html18
-rw-r--r--chromium/content/browser/resources/media/new/media_internals.js18
-rw-r--r--chromium/content/browser/resources/media/new/player_info_test.html146
-rw-r--r--chromium/content/browser/resources/media/new/player_manager.js111
-rw-r--r--chromium/content/browser/resources/media/new/player_manager_test.html155
-rw-r--r--chromium/content/browser/resources/media/new/util.js34
-rw-r--r--chromium/content/browser/resources/media/new/webui_resource_test.js210
-rw-r--r--chromium/content/browser/resources/media/player_info.js (renamed from chromium/content/browser/resources/media/new/player_info.js)0
-rw-r--r--chromium/content/browser/resources/media/util.js103
-rw-r--r--chromium/content/browser/resources/media/webrtc_internals.js2
-rw-r--r--chromium/content/browser/security_exploit_browsertest.cc2
-rw-r--r--chromium/content/browser/service_worker/OWNERS3
-rw-r--r--chromium/content/browser/service_worker/service_worker_context.cc25
-rw-r--r--chromium/content/browser/service_worker/service_worker_context.h44
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host.cc50
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host.h40
-rw-r--r--chromium/content/browser/session_history_browsertest.cc4
-rw-r--r--chromium/content/browser/site_instance_impl.cc2
-rw-r--r--chromium/content/browser/site_per_process_browsertest.cc2
-rw-r--r--chromium/content/browser/speech/OWNERS1
-rw-r--r--chromium/content/browser/speech/google_streaming_remote_engine_unittest.cc18
-rw-r--r--chromium/content/browser/speech/input_tag_speech_browsertest.cc (renamed from chromium/content/browser/speech/speech_recognition_browsertest.cc)16
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl.cc2
-rw-r--r--chromium/content/browser/ssl/ssl_manager.cc72
-rw-r--r--chromium/content/browser/ssl/ssl_manager.h32
-rw-r--r--chromium/content/browser/startup_task_runner.cc63
-rw-r--r--chromium/content/browser/startup_task_runner.h20
-rw-r--r--chromium/content/browser/startup_task_runner_unittest.cc112
-rw-r--r--chromium/content/browser/storage_partition_impl.cc11
-rw-r--r--chromium/content/browser/storage_partition_impl.h5
-rw-r--r--chromium/content/browser/storage_partition_impl_map.cc84
-rw-r--r--chromium/content/browser/storage_partition_impl_unittest.cc2
-rw-r--r--chromium/content/browser/streams/stream.cc59
-rw-r--r--chromium/content/browser/streams/stream.h24
-rw-r--r--chromium/content/browser/streams/stream_registry.cc46
-rw-r--r--chromium/content/browser/streams/stream_registry.h21
-rw-r--r--chromium/content/browser/streams/stream_unittest.cc109
-rw-r--r--chromium/content/browser/streams/stream_url_request_job.cc54
-rw-r--r--chromium/content/browser/streams/stream_url_request_job_unittest.cc1
-rw-r--r--chromium/content/browser/tracing/OWNERS1
-rw-r--r--chromium/content/browser/tracing/trace_controller_impl.cc56
-rw-r--r--chromium/content/browser/tracing/trace_controller_impl.h5
-rw-r--r--chromium/content/browser/tracing/trace_message_filter.h2
-rw-r--r--chromium/content/browser/tracing/trace_subscriber_stdio.cc158
-rw-r--r--chromium/content/browser/tracing/trace_subscriber_stdio.h25
-rw-r--r--chromium/content/browser/tracing/trace_subscriber_stdio_unittest.cc98
-rw-r--r--chromium/content/browser/tracing/tracing_controller_browsertest.cc115
-rw-r--r--chromium/content/browser/tracing/tracing_controller_impl.cc270
-rw-r--r--chromium/content/browser/tracing/tracing_controller_impl.h100
-rw-r--r--chromium/content/browser/tracing/tracing_ui.cc8
-rw-r--r--chromium/content/browser/utility_process_host_impl.cc73
-rw-r--r--chromium/content/browser/utility_process_host_impl.h11
-rw-r--r--chromium/content/browser/web_contents/aura/image_window_delegate.cc5
-rw-r--r--chromium/content/browser/web_contents/aura/image_window_delegate.h3
-rw-r--r--chromium/content/browser/web_contents/aura/window_slider.cc31
-rw-r--r--chromium/content/browser/web_contents/aura/window_slider.h7
-rw-r--r--chromium/content/browser/web_contents/interstitial_page_impl.cc6
-rw-r--r--chromium/content/browser/web_contents/navigation_controller_impl.cc20
-rw-r--r--chromium/content/browser/web_contents/navigation_controller_impl.h3
-rw-r--r--chromium/content/browser/web_contents/navigation_controller_impl_unittest.cc34
-rw-r--r--chromium/content/browser/web_contents/navigation_entry_impl.cc14
-rw-r--r--chromium/content/browser/web_contents/navigation_entry_impl.h3
-rw-r--r--chromium/content/browser/web_contents/render_view_host_manager.cc76
-rw-r--r--chromium/content/browser/web_contents/render_view_host_manager.h8
-rw-r--r--chromium/content/browser/web_contents/render_view_host_manager_unittest.cc22
-rw-r--r--chromium/content/browser/web_contents/touch_editable_impl_aura.cc4
-rw-r--r--chromium/content/browser/web_contents/touch_editable_impl_aura_browsertest.cc75
-rw-r--r--chromium/content/browser/web_contents/web_contents_drag_win.cc2
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl.cc333
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl.h22
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl_browsertest.cc135
-rw-r--r--chromium/content/browser/web_contents/web_contents_screenshot_manager.cc6
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_android.cc2
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura.cc58
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura.h3
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc95
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_mac.mm12
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_win.cc1
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_win.h4
-rw-r--r--chromium/content/browser/web_contents/web_drag_source_gtk.cc2
-rw-r--r--chromium/content/browser/web_contents/web_drag_source_mac.h6
-rw-r--r--chromium/content/browser/web_contents/web_drag_source_mac.mm200
-rw-r--r--chromium/content/browser/webkit_browsertest.cc2
-rw-r--r--chromium/content/browser/webui/shared_resources_data_source.cc30
-rw-r--r--chromium/content/browser/webui/url_data_manager_backend.cc2
-rw-r--r--chromium/content/browser/webui/web_ui_controller_factory_registry.cc2
-rw-r--r--chromium/content/browser/webui/web_ui_data_source_impl.cc13
-rw-r--r--chromium/content/browser/webui/web_ui_data_source_impl.h2
-rw-r--r--chromium/content/browser/worker_host/message_port_service.cc4
-rw-r--r--chromium/content/browser/worker_host/message_port_service.h7
-rw-r--r--chromium/content/browser/worker_host/worker_process_host.cc59
-rw-r--r--chromium/content/browser/worker_host/worker_process_host.h13
-rw-r--r--chromium/content/browser/worker_host/worker_service_impl.cc14
-rw-r--r--chromium/content/browser/zygote_host/zygote_host_impl_linux.cc4
-rw-r--r--chromium/content/browser/zygote_host/zygote_host_impl_linux.h6
637 files changed, 23279 insertions, 14619 deletions
diff --git a/chromium/content/browser/DEPS b/chromium/content/browser/DEPS
index 39be9891906..2a42e40f7e3 100644
--- a/chromium/content/browser/DEPS
+++ b/chromium/content/browser/DEPS
@@ -1,5 +1,4 @@
include_rules = [
- "+content/gpu", # For gpu_info_collector.h and in-process GPU
"+content/port/browser",
"+content/public/browser",
"+content/child/webkitplatformsupport_impl.h", # For in-process webkit
@@ -10,10 +9,6 @@ include_rules = [
"+ui/webui",
"+win8/util",
- # For single-process mode.
- "+content/child/child_process.h",
- "+content/utility/utility_thread_impl.h",
-
# TODO(joi): This was misplaced; need to move it somewhere else,
# since //content shouldn't depend on //components, which is a layer
# above.
@@ -45,6 +40,7 @@ include_rules = [
"+third_party/WebKit/public/platform/WebScreenInfo.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",
@@ -61,7 +57,6 @@ include_rules = [
"+third_party/WebKit/public/web/WebTextDirection.h",
# These should be burned down. http://crbug.com/237267
- "!third_party/WebKit/public/web/gtk/WebInputEventFactory.h",
"!third_party/WebKit/public/web/mac/WebInputEventFactory.h",
# DO NOT ADD ANY CHROME OR COMPONENTS INCLUDES HERE!!!
diff --git a/chromium/content/browser/accessibility/accessibility_ui.cc b/chromium/content/browser/accessibility/accessibility_ui.cc
index 585be6806a1..d5a9734b0eb 100644
--- a/chromium/content/browser/accessibility/accessibility_ui.cc
+++ b/chromium/content/browser/accessibility/accessibility_ui.cc
@@ -22,6 +22,7 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/render_widget_host_iterator.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/common/url_constants.h"
@@ -91,15 +92,16 @@ void SendTargetsData(
const WebUIDataSource::GotDataCallback& callback) {
scoped_ptr<base::ListValue> rvh_list(new base::ListValue());
- RenderWidgetHost::List widgets = RenderWidgetHost::GetRenderWidgetHosts();
- for (size_t i = 0; i < widgets.size(); ++i) {
+ scoped_ptr<RenderWidgetHostIterator> widgets(
+ RenderWidgetHost::GetRenderWidgetHosts());
+ while (RenderWidgetHost* widget = widgets->GetNextHost()) {
// Ignore processes that don't have a connection, such as crashed tabs.
- if (!widgets[i]->GetProcess()->HasConnection())
+ if (!widget->GetProcess()->HasConnection())
continue;
- if (!widgets[i]->IsRenderView())
+ if (!widget->IsRenderView())
continue;
- RenderViewHost* rvh = RenderViewHost::From(widgets[i]);
+ RenderViewHost* rvh = RenderViewHost::From(widget);
rvh_list->Append(BuildTargetDescriptor(rvh));
}
diff --git a/chromium/content/browser/accessibility/accessibility_win_browsertest.cc b/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
index 0be9ba5067d..6d069954117 100644
--- a/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
@@ -17,7 +17,7 @@
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/url_constants.h"
-#include "content/shell/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/accessibility_browser_test_utils.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
@@ -149,7 +149,7 @@ void AccessibilityWinBrowserTest::LoadInitialAccessibilityTreeFromHtml(
const std::string& html) {
AccessibilityNotificationWaiter waiter(
shell(), AccessibilityModeComplete,
- AccessibilityNotificationLoadComplete);
+ WebKit::WebAXEventLoadComplete);
GURL html_data_url("data:text/html," + html);
NavigateToURL(shell(), html_data_url);
waiter.WaitForNotification();
@@ -504,7 +504,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
scoped_ptr<AccessibilityNotificationWaiter> waiter(
new AccessibilityNotificationWaiter(
shell(), AccessibilityModeComplete,
- AccessibilityNotificationFocusChanged));
+ WebKit::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,
- AccessibilityNotificationFocusChanged));
+ WebKit::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,
- AccessibilityNotificationCheckStateChanged));
+ WebKit::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,
- AccessibilityNotificationChildrenChanged));
+ WebKit::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,
- AccessibilityNotificationChildrenChanged));
+ WebKit::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,
- AccessibilityNotificationFocusChanged));
+ WebKit::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,
- AccessibilityNotificationBlur));
+ WebKit::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,
- AccessibilityNotificationValueChanged));
+ WebKit::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 ae7efe2f660..e039cc71e69 100644
--- a/chromium/content/browser/accessibility/browser_accessibility.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility.cc
@@ -7,6 +7,7 @@
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/common/accessibility_messages.h"
@@ -64,22 +65,20 @@ void BrowserAccessibility::InitializeTreeStructure(
void BrowserAccessibility::InitializeData(const AccessibilityNodeData& src) {
DCHECK_EQ(renderer_id_, src.id);
- name_ = src.name;
- value_ = src.value;
role_ = src.role;
state_ = src.state;
string_attributes_ = src.string_attributes;
int_attributes_ = src.int_attributes;
float_attributes_ = src.float_attributes;
bool_attributes_ = src.bool_attributes;
+ intlist_attributes_ = src.intlist_attributes;
html_attributes_ = src.html_attributes;
location_ = src.location;
- indirect_child_ids_ = src.indirect_child_ids;
- line_breaks_ = src.line_breaks;
- cell_ids_ = src.cell_ids;
- unique_cell_ids_ = src.unique_cell_ids;
instance_active_ = true;
+ GetStringAttribute(AccessibilityNodeData::ATTR_NAME, &name_);
+ GetStringAttribute(AccessibilityNodeData::ATTR_VALUE, &value_);
+
PreInitialize();
}
@@ -143,8 +142,8 @@ gfx::Rect BrowserAccessibility::GetLocalBoundsRect() const {
// nested web area.
BrowserAccessibility* parent = parent_;
bool need_to_offset_web_area =
- (role_ == AccessibilityNodeData::ROLE_WEB_AREA ||
- role_ == AccessibilityNodeData::ROLE_ROOT_WEB_AREA);
+ (role_ == WebKit::WebAXRoleWebArea ||
+ role_ == WebKit::WebAXRoleRootWebArea);
while (parent) {
if (need_to_offset_web_area &&
parent->location().width() > 0 &&
@@ -155,13 +154,13 @@ gfx::Rect BrowserAccessibility::GetLocalBoundsRect() const {
// On some platforms, we don't want to take the root scroll offsets
// into account.
- if (parent->role() == AccessibilityNodeData::ROLE_ROOT_WEB_AREA &&
+ if (parent->role() == WebKit::WebAXRoleRootWebArea &&
!manager()->UseRootScrollOffsetsWhenComputingBounds()) {
break;
}
- if (parent->role() == AccessibilityNodeData::ROLE_WEB_AREA ||
- parent->role() == AccessibilityNodeData::ROLE_ROOT_WEB_AREA) {
+ if (parent->role() == WebKit::WebAXRoleWebArea ||
+ parent->role() == WebKit::WebAXRoleRootWebArea) {
int sx = 0;
int sy = 0;
if (parent->GetIntAttribute(AccessibilityNodeData::ATTR_SCROLL_X, &sx) &&
@@ -212,7 +211,7 @@ void BrowserAccessibility::Destroy() {
PostInitialize();
manager_->NotifyAccessibilityEvent(
- AccessibilityNotificationObjectHide, this);
+ WebKit::WebAXEventHide, this);
instance_active_ = false;
manager_->RemoveNode(this);
@@ -223,55 +222,197 @@ void BrowserAccessibility::NativeReleaseReference() {
delete this;
}
+bool BrowserAccessibility::HasBoolAttribute(BoolAttribute attribute) const {
+ for (size_t i = 0; i < bool_attributes_.size(); ++i) {
+ if (bool_attributes_[i].first == attribute)
+ return true;
+ }
+
+ return false;
+}
+
+
+bool BrowserAccessibility::GetBoolAttribute(BoolAttribute attribute) const {
+ for (size_t i = 0; i < bool_attributes_.size(); ++i) {
+ if (bool_attributes_[i].first == attribute)
+ return bool_attributes_[i].second;
+ }
+
+ return false;
+}
+
bool BrowserAccessibility::GetBoolAttribute(
BoolAttribute attribute, bool* value) const {
- BoolAttrMap::const_iterator iter = bool_attributes_.find(attribute);
- if (iter != bool_attributes_.end()) {
- *value = iter->second;
- return true;
+ for (size_t i = 0; i < bool_attributes_.size(); ++i) {
+ if (bool_attributes_[i].first == attribute) {
+ *value = bool_attributes_[i].second;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool BrowserAccessibility::HasFloatAttribute(FloatAttribute attribute) const {
+ for (size_t i = 0; i < float_attributes_.size(); ++i) {
+ if (float_attributes_[i].first == attribute)
+ return true;
}
return false;
}
+float BrowserAccessibility::GetFloatAttribute(FloatAttribute attribute) const {
+ for (size_t i = 0; i < float_attributes_.size(); ++i) {
+ if (float_attributes_[i].first == attribute)
+ return float_attributes_[i].second;
+ }
+
+ return 0.0;
+}
+
bool BrowserAccessibility::GetFloatAttribute(
FloatAttribute attribute, float* value) const {
- FloatAttrMap::const_iterator iter = float_attributes_.find(attribute);
- if (iter != float_attributes_.end()) {
- *value = iter->second;
- return true;
+ for (size_t i = 0; i < float_attributes_.size(); ++i) {
+ if (float_attributes_[i].first == attribute) {
+ *value = float_attributes_[i].second;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool BrowserAccessibility::HasIntAttribute(IntAttribute attribute) const {
+ for (size_t i = 0; i < int_attributes_.size(); ++i) {
+ if (int_attributes_[i].first == attribute)
+ return true;
}
return false;
}
+int BrowserAccessibility::GetIntAttribute(IntAttribute attribute) const {
+ for (size_t i = 0; i < int_attributes_.size(); ++i) {
+ if (int_attributes_[i].first == attribute)
+ return int_attributes_[i].second;
+ }
+
+ return 0;
+}
+
bool BrowserAccessibility::GetIntAttribute(
IntAttribute attribute, int* value) const {
- IntAttrMap::const_iterator iter = int_attributes_.find(attribute);
- if (iter != int_attributes_.end()) {
- *value = iter->second;
- return true;
+ for (size_t i = 0; i < int_attributes_.size(); ++i) {
+ if (int_attributes_[i].first == attribute) {
+ *value = int_attributes_[i].second;
+ return true;
+ }
}
return false;
}
+bool BrowserAccessibility::HasStringAttribute(StringAttribute attribute) const {
+ for (size_t i = 0; i < string_attributes_.size(); ++i) {
+ if (string_attributes_[i].first == attribute)
+ return true;
+ }
+
+ return false;
+}
+
+const std::string& BrowserAccessibility::GetStringAttribute(
+ StringAttribute attribute) const {
+ CR_DEFINE_STATIC_LOCAL(std::string, empty_string, ());
+ for (size_t i = 0; i < string_attributes_.size(); ++i) {
+ if (string_attributes_[i].first == attribute)
+ return string_attributes_[i].second;
+ }
+
+ return empty_string;
+}
+
bool BrowserAccessibility::GetStringAttribute(
+ StringAttribute attribute, std::string* value) const {
+ for (size_t i = 0; i < string_attributes_.size(); ++i) {
+ if (string_attributes_[i].first == attribute) {
+ *value = string_attributes_[i].second;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+string16 BrowserAccessibility::GetString16Attribute(
+ StringAttribute attribute) const {
+ std::string value_utf8;
+ if (!GetStringAttribute(attribute, &value_utf8))
+ return string16();
+ return UTF8ToUTF16(value_utf8);
+}
+
+bool BrowserAccessibility::GetString16Attribute(
StringAttribute attribute,
string16* value) const {
- StringAttrMap::const_iterator iter = string_attributes_.find(attribute);
- if (iter != string_attributes_.end()) {
- *value = iter->second;
- return true;
+ std::string value_utf8;
+ if (!GetStringAttribute(attribute, &value_utf8))
+ return false;
+ *value = UTF8ToUTF16(value_utf8);
+ return true;
+}
+
+void BrowserAccessibility::SetStringAttribute(
+ StringAttribute attribute, const std::string& value) {
+ for (size_t i = 0; i < string_attributes_.size(); ++i) {
+ if (string_attributes_[i].first == attribute) {
+ string_attributes_[i].second = value;
+ return;
+ }
+ }
+ if (!value.empty())
+ string_attributes_.push_back(std::make_pair(attribute, value));
+}
+
+bool BrowserAccessibility::HasIntListAttribute(
+ AccessibilityNodeData::IntListAttribute attribute) const {
+ for (size_t i = 0; i < intlist_attributes_.size(); ++i) {
+ if (intlist_attributes_[i].first == attribute)
+ return true;
+ }
+
+ return false;
+}
+
+const std::vector<int32>& BrowserAccessibility::GetIntListAttribute(
+ AccessibilityNodeData::IntListAttribute attribute) const {
+ CR_DEFINE_STATIC_LOCAL(std::vector<int32>, empty_vector, ());
+ for (size_t i = 0; i < intlist_attributes_.size(); ++i) {
+ if (intlist_attributes_[i].first == attribute)
+ return intlist_attributes_[i].second;
+ }
+
+ return empty_vector;
+}
+
+bool BrowserAccessibility::GetIntListAttribute(
+ AccessibilityNodeData::IntListAttribute attribute,
+ std::vector<int32>* value) const {
+ for (size_t i = 0; i < intlist_attributes_.size(); ++i) {
+ if (intlist_attributes_[i].first == attribute) {
+ *value = intlist_attributes_[i].second;
+ return true;
+ }
}
return false;
}
bool BrowserAccessibility::GetHtmlAttribute(
- const char* html_attr, string16* value) const {
+ const char* html_attr, std::string* value) const {
for (size_t i = 0; i < html_attributes_.size(); i++) {
- const string16& attr = html_attributes_[i].first;
+ const std::string& attr = html_attributes_[i].first;
if (LowerCaseEqualsASCII(attr, html_attr)) {
*value = html_attributes_[i].second;
return true;
@@ -281,6 +422,15 @@ bool BrowserAccessibility::GetHtmlAttribute(
return false;
}
+bool BrowserAccessibility::GetHtmlAttribute(
+ const char* html_attr, string16* value) const {
+ std::string value_utf8;
+ if (!GetHtmlAttribute(html_attr, &value_utf8))
+ return false;
+ *value = UTF8ToUTF16(value_utf8);
+ return true;
+}
+
bool BrowserAccessibility::GetAriaTristate(
const char* html_attr,
bool* is_defined,
@@ -306,33 +456,32 @@ bool BrowserAccessibility::GetAriaTristate(
return false; // Not set
}
-bool BrowserAccessibility::HasState(
- AccessibilityNodeData::State state_enum) const {
+bool BrowserAccessibility::HasState(WebKit::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_ == AccessibilityNodeData::ROLE_SCROLLAREA ||
- role_ == AccessibilityNodeData::ROLE_COLUMN ||
- role_ == AccessibilityNodeData::ROLE_TABLE_HEADER_CONTAINER) {
+ if (role_ == WebKit::WebAXRoleScrollArea ||
+ role_ == WebKit::WebAXRoleColumn ||
+ role_ == WebKit::WebAXRoleTableHeaderContainer) {
return false;
}
- // Note: STATE_READONLY being false means it's either a text control,
+ // 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(AccessibilityNodeData::STATE_READONLY) ||
- role_ == AccessibilityNodeData::ROLE_TEXT_FIELD ||
- role_ == AccessibilityNodeData::ROLE_TEXTAREA);
+ return (!HasState(WebKit::WebAXStateReadonly) ||
+ role_ == WebKit::WebAXRoleTextField ||
+ role_ == WebKit::WebAXRoleTextArea);
}
-string16 BrowserAccessibility::GetTextRecursive() const {
+std::string BrowserAccessibility::GetTextRecursive() const {
if (!name_.empty()) {
return name_;
}
- string16 result;
+ std::string result;
for (size_t i = 0; i < children_.size(); ++i)
result += children_[i]->GetTextRecursive();
return result;
diff --git a/chromium/content/browser/accessibility/browser_accessibility.h b/chromium/content/browser/accessibility/browser_accessibility.h
index 8fda68fc079..a52075128a5 100644
--- a/chromium/content/browser/accessibility/browser_accessibility.h
+++ b/chromium/content/browser/accessibility/browser_accessibility.h
@@ -10,9 +10,11 @@
#include <vector>
#include "base/basictypes.h"
+#include "base/strings/string16.h"
#include "build/build_config.h"
#include "content/common/accessibility_node_data.h"
#include "content/common/content_export.h"
+#include "third_party/WebKit/public/web/WebAXEnums.h"
#if defined(OS_MACOSX) && __OBJC__
@class BrowserAccessibilityCocoa;
@@ -26,12 +28,6 @@ class BrowserAccessibilityWin;
class BrowserAccessibilityGtk;
#endif
-typedef std::map<AccessibilityNodeData::BoolAttribute, bool> BoolAttrMap;
-typedef std::map<AccessibilityNodeData::FloatAttribute, float> FloatAttrMap;
-typedef std::map<AccessibilityNodeData::IntAttribute, int> IntAttrMap;
-typedef std::map<AccessibilityNodeData::StringAttribute, string16>
- StringAttrMap;
-
////////////////////////////////////////////////////////////////////////////////
//
// BrowserAccessibility
@@ -136,49 +132,21 @@ class CONTENT_EXPORT BrowserAccessibility {
// Accessors
//
- const BoolAttrMap& bool_attributes() const {
- return bool_attributes_;
- }
-
- const FloatAttrMap& float_attributes() const {
- return float_attributes_;
- }
-
- const IntAttrMap& int_attributes() const {
- return int_attributes_;
- }
-
- const StringAttrMap& string_attributes() const {
- return string_attributes_;
- }
-
const std::vector<BrowserAccessibility*>& children() const {
return children_;
}
- const std::vector<std::pair<string16, string16> >& html_attributes() const {
+ const std::vector<std::pair<std::string, std::string> >&
+ html_attributes() const {
return html_attributes_;
}
int32 index_in_parent() const { return index_in_parent_; }
- const std::vector<int32>& indirect_child_ids() const {
- return indirect_child_ids_;
- }
- const std::vector<int32>& line_breaks() const {
- return line_breaks_;
- }
- const std::vector<int32>& cell_ids() const {
- return cell_ids_;
- }
- const std::vector<int32>& unique_cell_ids() const {
- return unique_cell_ids_;
- }
gfx::Rect location() const { return location_; }
BrowserAccessibilityManager* manager() const { return manager_; }
- const string16& name() const { return name_; }
+ const std::string& name() const { return name_; }
int32 renderer_id() const { return renderer_id_; }
int32 role() const { return role_; }
- const string16& role_name() const { return role_name_; }
int32 state() const { return state_; }
- const string16& value() const { return value_; }
+ const std::string& value() const { return value_; }
bool instance_active() const { return instance_active_; }
#if defined(OS_MACOSX) && __OBJC__
@@ -189,29 +157,63 @@ class CONTENT_EXPORT BrowserAccessibility {
BrowserAccessibilityGtk* ToBrowserAccessibilityGtk();
#endif
- // Retrieve the value of a bool attribute from the bool attribute
- // map and returns true if found.
- bool GetBoolAttribute(
- AccessibilityNodeData::BoolAttribute attr, bool* value) const;
-
- // Retrieve the value of a float attribute from the float attribute
- // map and returns true if found.
+ // Accessing accessibility attributes:
+ //
+ // There are dozens of possible attributes for an accessibility node,
+ // but only a few tend to apply to any one object, so we store them
+ // in sparse arrays of <attribute id, attribute value> pairs, organized
+ // by type (bool, int, float, string, int list).
+ //
+ // There are three accessors for each type of attribute: one that returns
+ // true if the attribute is present and false if not, one that takes a
+ // pointer argument and returns true if the attribute is present (if you
+ // 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.
+
+ bool HasBoolAttribute(AccessibilityNodeData::BoolAttribute attr) const;
+ bool GetBoolAttribute(AccessibilityNodeData::BoolAttribute attr) const;
+ bool GetBoolAttribute(AccessibilityNodeData::BoolAttribute attr,
+ bool* value) const;
+
+ bool HasFloatAttribute(AccessibilityNodeData::FloatAttribute attr) const;
+ float GetFloatAttribute(AccessibilityNodeData::FloatAttribute attr) const;
bool GetFloatAttribute(AccessibilityNodeData::FloatAttribute attr,
float* value) const;
- // Retrieve the value of an integer attribute from the integer attribute
- // map and returns true if found.
+ bool HasIntAttribute(AccessibilityNodeData::IntAttribute attribute) const;
+ int GetIntAttribute(AccessibilityNodeData::IntAttribute attribute) const;
bool GetIntAttribute(AccessibilityNodeData::IntAttribute attribute,
int* value) const;
- // Retrieve the value of a string attribute from the attribute map and
- // returns true if found.
- bool GetStringAttribute(
- AccessibilityNodeData::StringAttribute attribute, string16* value) const;
+ bool HasStringAttribute(
+ AccessibilityNodeData::StringAttribute attribute) const;
+ const std::string& GetStringAttribute(
+ AccessibilityNodeData::StringAttribute attribute) const;
+ bool GetStringAttribute(AccessibilityNodeData::StringAttribute attribute,
+ std::string* value) const;
+
+ bool GetString16Attribute(AccessibilityNodeData::StringAttribute attribute,
+ string16* value) const;
+ string16 GetString16Attribute(
+ AccessibilityNodeData::StringAttribute attribute) const;
+
+ bool HasIntListAttribute(
+ AccessibilityNodeData::IntListAttribute attribute) const;
+ const std::vector<int32>& GetIntListAttribute(
+ AccessibilityNodeData::IntListAttribute attribute) const;
+ bool GetIntListAttribute(AccessibilityNodeData::IntListAttribute attribute,
+ std::vector<int32>* value) const;
+
+ void SetStringAttribute(
+ AccessibilityNodeData::StringAttribute attribute,
+ const std::string& value);
// 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, std::string* value) const;
// Utility method to handle special cases for ARIA booleans, tristates and
// booleans which have a "mixed" state.
@@ -230,13 +232,13 @@ class CONTENT_EXPORT BrowserAccessibility {
bool* is_mixed) const;
// Returns true if the bit corresponding to the given state enum is 1.
- bool HasState(AccessibilityNodeData::State state_enum) const;
+ bool HasState(WebKit::WebAXState state_enum) const;
// Returns true if this node is an editable text field of any kind.
bool IsEditableText() const;
// Append the text from this node and its children.
- string16 GetTextRecursive() const;
+ std::string GetTextRecursive() const;
protected:
// Perform platform specific initialization. This can be called multiple times
@@ -264,21 +266,23 @@ class CONTENT_EXPORT BrowserAccessibility {
std::vector<BrowserAccessibility*> children_;
// Accessibility metadata from the renderer
- string16 name_;
- string16 value_;
- BoolAttrMap bool_attributes_;
- IntAttrMap int_attributes_;
- FloatAttrMap float_attributes_;
- StringAttrMap string_attributes_;
- std::vector<std::pair<string16, string16> > html_attributes_;
+ std::string name_;
+ std::string value_;
+ std::vector<std::pair<
+ AccessibilityNodeData::BoolAttribute, bool> > bool_attributes_;
+ std::vector<std::pair<
+ AccessibilityNodeData::FloatAttribute, float> > float_attributes_;
+ std::vector<std::pair<
+ AccessibilityNodeData::IntAttribute, int> > int_attributes_;
+ std::vector<std::pair<
+ AccessibilityNodeData::StringAttribute, std::string> > string_attributes_;
+ std::vector<std::pair<
+ AccessibilityNodeData::IntListAttribute, std::vector<int32> > >
+ intlist_attributes_;
+ std::vector<std::pair<std::string, std::string> > html_attributes_;
int32 role_;
int32 state_;
- string16 role_name_;
gfx::Rect location_;
- std::vector<int32> indirect_child_ids_;
- std::vector<int32> line_breaks_;
- std::vector<int32> cell_ids_;
- std::vector<int32> unique_cell_ids_;
// BrowserAccessibility objects are reference-counted on some platforms.
// When we're done with this object and it's removed from our accessibility
diff --git a/chromium/content/browser/accessibility/browser_accessibility_android.cc b/chromium/content/browser/accessibility/browser_accessibility_android.cc
index 8ff37ec0c7d..d8899d7d31c 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_android.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_android.cc
@@ -30,8 +30,8 @@ bool BrowserAccessibilityAndroid::IsLeaf() const {
// Iframes are always allowed to contain children.
if (IsIframe() ||
- role() == AccessibilityNodeData::ROLE_ROOT_WEB_AREA ||
- role() == AccessibilityNodeData::ROLE_WEB_AREA) {
+ role() == WebKit::WebAXRoleRootWebArea ||
+ role() == WebKit::WebAXRoleWebArea) {
return false;
}
@@ -41,11 +41,11 @@ bool BrowserAccessibilityAndroid::IsLeaf() const {
// Headings with text can drop their children.
string16 name = GetText();
- if (role() == AccessibilityNodeData::ROLE_HEADING && !name.empty())
+ if (role() == WebKit::WebAXRoleHeading && !name.empty())
return true;
// Focusable nodes with text can drop their children.
- if (HasState(AccessibilityNodeData::STATE_FOCUSABLE) && !name.empty())
+ if (HasState(WebKit::WebAXStateFocusable) && !name.empty())
return true;
// Nodes with only static text as children can drop their children.
@@ -60,18 +60,18 @@ bool BrowserAccessibilityAndroid::IsCheckable() const {
bool is_aria_pressed_defined;
bool is_mixed;
GetAriaTristate("aria-pressed", &is_aria_pressed_defined, &is_mixed);
- if (role() == AccessibilityNodeData::ROLE_CHECKBOX ||
- role() == AccessibilityNodeData::ROLE_RADIO_BUTTON ||
+ if (role() == WebKit::WebAXRoleCheckBox ||
+ role() == WebKit::WebAXRoleRadioButton ||
is_aria_pressed_defined) {
checkable = true;
}
- if (HasState(AccessibilityNodeData::STATE_CHECKED))
+ if (HasState(WebKit::WebAXStateChecked))
checkable = true;
return checkable;
}
bool BrowserAccessibilityAndroid::IsChecked() const {
- return HasState(AccessibilityNodeData::STATE_CHECKED);
+ return HasState(WebKit::WebAXStateChecked);
}
bool BrowserAccessibilityAndroid::IsClickable() const {
@@ -79,13 +79,13 @@ bool BrowserAccessibilityAndroid::IsClickable() const {
}
bool BrowserAccessibilityAndroid::IsEnabled() const {
- return !HasState(AccessibilityNodeData::STATE_UNAVAILABLE);
+ return HasState(WebKit::WebAXStateEnabled);
}
bool BrowserAccessibilityAndroid::IsFocusable() const {
- bool focusable = HasState(AccessibilityNodeData::STATE_FOCUSABLE);
+ bool focusable = HasState(WebKit::WebAXStateFocusable);
if (IsIframe() ||
- role() == AccessibilityNodeData::ROLE_WEB_AREA) {
+ role() == WebKit::WebAXRoleWebArea) {
focusable = false;
}
return focusable;
@@ -96,7 +96,7 @@ bool BrowserAccessibilityAndroid::IsFocused() const {
}
bool BrowserAccessibilityAndroid::IsPassword() const {
- return HasState(AccessibilityNodeData::STATE_PROTECTED);
+ return HasState(WebKit::WebAXStateProtected);
}
bool BrowserAccessibilityAndroid::IsScrollable() const {
@@ -105,59 +105,59 @@ bool BrowserAccessibilityAndroid::IsScrollable() const {
}
bool BrowserAccessibilityAndroid::IsSelected() const {
- return HasState(AccessibilityNodeData::STATE_SELECTED);
+ return HasState(WebKit::WebAXStateSelected);
}
bool BrowserAccessibilityAndroid::IsVisibleToUser() const {
- return !HasState(AccessibilityNodeData::STATE_INVISIBLE);
+ return !HasState(WebKit::WebAXStateInvisible);
}
const char* BrowserAccessibilityAndroid::GetClassName() const {
const char* class_name = NULL;
switch(role()) {
- case AccessibilityNodeData::ROLE_EDITABLE_TEXT:
- case AccessibilityNodeData::ROLE_SPIN_BUTTON:
- case AccessibilityNodeData::ROLE_TEXTAREA:
- case AccessibilityNodeData::ROLE_TEXT_FIELD:
+ case WebKit::WebAXRoleEditableText:
+ case WebKit::WebAXRoleSpinButton:
+ case WebKit::WebAXRoleTextArea:
+ case WebKit::WebAXRoleTextField:
class_name = "android.widget.EditText";
break;
- case AccessibilityNodeData::ROLE_SLIDER:
+ case WebKit::WebAXRoleSlider:
class_name = "android.widget.SeekBar";
break;
- case AccessibilityNodeData::ROLE_COMBO_BOX:
+ case WebKit::WebAXRoleComboBox:
class_name = "android.widget.Spinner";
break;
- case AccessibilityNodeData::ROLE_BUTTON:
- case AccessibilityNodeData::ROLE_MENU_BUTTON:
- case AccessibilityNodeData::ROLE_POPUP_BUTTON:
+ case WebKit::WebAXRoleButton:
+ case WebKit::WebAXRoleMenuButton:
+ case WebKit::WebAXRolePopUpButton:
class_name = "android.widget.Button";
break;
- case AccessibilityNodeData::ROLE_CHECKBOX:
+ case WebKit::WebAXRoleCheckBox:
class_name = "android.widget.CheckBox";
break;
- case AccessibilityNodeData::ROLE_RADIO_BUTTON:
+ case WebKit::WebAXRoleRadioButton:
class_name = "android.widget.RadioButton";
break;
- case AccessibilityNodeData::ROLE_TOGGLE_BUTTON:
+ case WebKit::WebAXRoleToggleButton:
class_name = "android.widget.ToggleButton";
break;
- case AccessibilityNodeData::ROLE_CANVAS:
- case AccessibilityNodeData::ROLE_IMAGE:
+ case WebKit::WebAXRoleCanvas:
+ case WebKit::WebAXRoleImage:
class_name = "android.widget.Image";
break;
- case AccessibilityNodeData::ROLE_PROGRESS_INDICATOR:
+ case WebKit::WebAXRoleProgressIndicator:
class_name = "android.widget.ProgressBar";
break;
- case AccessibilityNodeData::ROLE_TAB_LIST:
+ case WebKit::WebAXRoleTabList:
class_name = "android.widget.TabWidget";
break;
- case AccessibilityNodeData::ROLE_GRID:
- case AccessibilityNodeData::ROLE_TABLE:
+ case WebKit::WebAXRoleGrid:
+ case WebKit::WebAXRoleTable:
class_name = "android.widget.GridView";
break;
- case AccessibilityNodeData::ROLE_LIST:
- case AccessibilityNodeData::ROLE_LISTBOX:
+ case WebKit::WebAXRoleList:
+ case WebKit::WebAXRoleListBox:
class_name = "android.widget.ListView";
break;
default:
@@ -170,20 +170,19 @@ const char* BrowserAccessibilityAndroid::GetClassName() const {
string16 BrowserAccessibilityAndroid::GetText() const {
if (IsIframe() ||
- role() == AccessibilityNodeData::ROLE_WEB_AREA) {
+ role() == WebKit::WebAXRoleWebArea) {
return string16();
}
- string16 description;
- GetStringAttribute(AccessibilityNodeData::ATTR_DESCRIPTION, &description);
-
+ string16 description = GetString16Attribute(
+ AccessibilityNodeData::ATTR_DESCRIPTION);
string16 text;
if (!name().empty())
- text = name();
+ text = base::UTF8ToUTF16(name());
else if (!description.empty())
text = description;
else if (!value().empty())
- text = value();
+ text = base::UTF8ToUTF16(value());
if (text.empty() && HasOnlyStaticTextChildren()) {
for (uint32 i = 0; i < child_count(); i++) {
@@ -193,14 +192,13 @@ string16 BrowserAccessibilityAndroid::GetText() const {
}
switch(role()) {
- case AccessibilityNodeData::ROLE_IMAGE_MAP_LINK:
- case AccessibilityNodeData::ROLE_LINK:
- case AccessibilityNodeData::ROLE_WEBCORE_LINK:
+ case WebKit::WebAXRoleImageMapLink:
+ case WebKit::WebAXRoleLink:
if (!text.empty())
text += ASCIIToUTF16(" ");
text += ASCIIToUTF16("Link");
break;
- case AccessibilityNodeData::ROLE_HEADING:
+ case WebKit::WebAXRoleHeading:
// Only append "heading" if this node already has text.
if (!text.empty())
text += ASCIIToUTF16(" Heading");
@@ -213,12 +211,12 @@ string16 BrowserAccessibilityAndroid::GetText() const {
int BrowserAccessibilityAndroid::GetItemIndex() const {
int index = 0;
switch(role()) {
- case AccessibilityNodeData::ROLE_LIST_ITEM:
- case AccessibilityNodeData::ROLE_LISTBOX_OPTION:
+ case WebKit::WebAXRoleListItem:
+ case WebKit::WebAXRoleListBoxOption:
index = index_in_parent();
break;
- case AccessibilityNodeData::ROLE_SLIDER:
- case AccessibilityNodeData::ROLE_PROGRESS_INDICATOR: {
+ case WebKit::WebAXRoleSlider:
+ case WebKit::WebAXRoleProgressIndicator: {
float value_for_range;
if (GetFloatAttribute(
AccessibilityNodeData::ATTR_VALUE_FOR_RANGE, &value_for_range)) {
@@ -233,12 +231,12 @@ int BrowserAccessibilityAndroid::GetItemIndex() const {
int BrowserAccessibilityAndroid::GetItemCount() const {
int count = 0;
switch(role()) {
- case AccessibilityNodeData::ROLE_LIST:
- case AccessibilityNodeData::ROLE_LISTBOX:
+ case WebKit::WebAXRoleList:
+ case WebKit::WebAXRoleListBox:
count = child_count();
break;
- case AccessibilityNodeData::ROLE_SLIDER:
- case AccessibilityNodeData::ROLE_PROGRESS_INDICATOR: {
+ case WebKit::WebAXRoleSlider:
+ case WebKit::WebAXRoleProgressIndicator: {
float max_value_for_range;
if (GetFloatAttribute(AccessibilityNodeData::ATTR_MAX_VALUE_FOR_RANGE,
&max_value_for_range)) {
@@ -343,7 +341,7 @@ int BrowserAccessibilityAndroid::GetEditableTextLength() const {
bool BrowserAccessibilityAndroid::HasFocusableChild() const {
for (uint32 i = 0; i < child_count(); i++) {
BrowserAccessibility* child = GetChild(i);
- if (child->HasState(AccessibilityNodeData::STATE_FOCUSABLE))
+ if (child->HasState(WebKit::WebAXStateFocusable))
return true;
if (static_cast<BrowserAccessibilityAndroid*>(child)->HasFocusableChild())
return true;
@@ -354,15 +352,15 @@ bool BrowserAccessibilityAndroid::HasFocusableChild() const {
bool BrowserAccessibilityAndroid::HasOnlyStaticTextChildren() const {
for (uint32 i = 0; i < child_count(); i++) {
BrowserAccessibility* child = GetChild(i);
- if (child->role() != AccessibilityNodeData::ROLE_STATIC_TEXT)
+ if (child->role() != WebKit::WebAXRoleStaticText)
return false;
}
return true;
}
bool BrowserAccessibilityAndroid::IsIframe() const {
- string16 html_tag;
- GetStringAttribute(AccessibilityNodeData::ATTR_HTML_TAG, &html_tag);
+ string16 html_tag = GetString16Attribute(
+ AccessibilityNodeData::ATTR_HTML_TAG);
return html_tag == ASCIIToUTF16("iframe");
}
@@ -370,18 +368,18 @@ void BrowserAccessibilityAndroid::PostInitialize() {
BrowserAccessibility::PostInitialize();
if (IsEditableText()) {
- if (value_ != new_value_) {
+ if (base::UTF8ToUTF16(value_) != new_value_) {
old_value_ = new_value_;
- new_value_ = value_;
+ new_value_ = base::UTF8ToUTF16(value_);
}
}
- if (role_ == AccessibilityNodeData::ROLE_ALERT && first_time_)
- manager_->NotifyAccessibilityEvent(AccessibilityNotificationAlert, this);
+ if (role_ == WebKit::WebAXRoleAlert && first_time_)
+ manager_->NotifyAccessibilityEvent(WebKit::WebAXEventAlert, this);
string16 live;
- if (GetStringAttribute(AccessibilityNodeData::ATTR_CONTAINER_LIVE_STATUS,
- &live)) {
+ if (GetString16Attribute(
+ AccessibilityNodeData::ATTR_CONTAINER_LIVE_STATUS, &live)) {
NotifyLiveRegionUpdate(live);
}
@@ -396,7 +394,7 @@ void BrowserAccessibilityAndroid::NotifyLiveRegionUpdate(string16& aria_live) {
string16 text = GetText();
if (cached_text_ != text) {
if (!text.empty()) {
- manager_->NotifyAccessibilityEvent(AccessibilityNotificationObjectShow,
+ manager_->NotifyAccessibilityEvent(WebKit::WebAXEventShow,
this);
}
cached_text_ = text;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_cocoa.h b/chromium/content/browser/accessibility/browser_accessibility_cocoa.h
index a394822961c..d690d81dd4d 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_cocoa.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_cocoa.h
@@ -10,7 +10,7 @@
#import "base/mac/scoped_nsobject.h"
#include "content/browser/accessibility/browser_accessibility.h"
#import "content/browser/accessibility/browser_accessibility_delegate_mac.h"
-#include "content/common/accessibility_node_data.h"
+#include "third_party/WebKit/public/web/WebAXEnums.h"
// BrowserAccessibilityCocoa is a cocoa wrapper around the BrowserAccessibility
// object. The renderer converts webkit's accessibility tree into a
@@ -40,7 +40,7 @@
// Convenience method to get the internal, cross-platform role
// from browserAccessibility_.
-- (content::AccessibilityNodeData::Role)internalRole;
+- (WebKit::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 9d49767d266..be9ff5b329d 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -33,161 +33,136 @@ namespace {
// Returns an autoreleased copy of the AccessibilityNodeData's attribute.
NSString* NSStringForStringAttribute(
- const std::map<StringAttribute, string16>& attributes,
+ BrowserAccessibility* browserAccessibility,
StringAttribute attribute) {
- std::map<StringAttribute, string16>::const_iterator iter =
- attributes.find(attribute);
- NSString* returnValue = @"";
- if (iter != attributes.end()) {
- returnValue = base::SysUTF16ToNSString(iter->second);
- }
- return returnValue;
+ return base::SysUTF8ToNSString(
+ browserAccessibility->GetStringAttribute(attribute));
}
struct MapEntry {
- AccessibilityNodeData::Role webKitValue;
+ WebKit::WebAXRole webKitValue;
NSString* nativeValue;
};
-typedef std::map<AccessibilityNodeData::Role, NSString*> RoleMap;
+typedef std::map<WebKit::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, int state) {
+bool GetState(BrowserAccessibility* accessibility, WebKit::WebAXState state) {
return ((accessibility->state() >> state) & 1);
}
RoleMap BuildRoleMap() {
const MapEntry roles[] = {
- { AccessibilityNodeData::ROLE_ALERT, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_ALERT_DIALOG, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_ANNOTATION, NSAccessibilityUnknownRole },
- { AccessibilityNodeData::ROLE_APPLICATION, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_ARTICLE, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_BROWSER, NSAccessibilityBrowserRole },
- { AccessibilityNodeData::ROLE_BUSY_INDICATOR,
- NSAccessibilityBusyIndicatorRole },
- { AccessibilityNodeData::ROLE_BUTTON, NSAccessibilityButtonRole },
- { AccessibilityNodeData::ROLE_CANVAS, NSAccessibilityImageRole },
- { AccessibilityNodeData::ROLE_CANVAS_WITH_FALLBACK_CONTENT,
- NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_CELL, @"AXCell" },
- { AccessibilityNodeData::ROLE_CHECKBOX, NSAccessibilityCheckBoxRole },
- { AccessibilityNodeData::ROLE_COLOR_WELL, NSAccessibilityColorWellRole },
- { AccessibilityNodeData::ROLE_COMBO_BOX, NSAccessibilityComboBoxRole },
- { AccessibilityNodeData::ROLE_COLUMN, NSAccessibilityColumnRole },
- { AccessibilityNodeData::ROLE_COLUMN_HEADER, @"AXCell" },
- { AccessibilityNodeData::ROLE_DEFINITION, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_DESCRIPTION_LIST_DETAIL,
- NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_DESCRIPTION_LIST_TERM,
- NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_DIALOG, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_DIRECTORY, NSAccessibilityListRole },
- { AccessibilityNodeData::ROLE_DISCLOSURE_TRIANGLE,
- NSAccessibilityDisclosureTriangleRole },
- { AccessibilityNodeData::ROLE_DIV, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_DOCUMENT, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_DRAWER, NSAccessibilityDrawerRole },
- { AccessibilityNodeData::ROLE_EDITABLE_TEXT, NSAccessibilityTextFieldRole },
- { AccessibilityNodeData::ROLE_FOOTER, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_FORM, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_GRID, NSAccessibilityGridRole },
- { AccessibilityNodeData::ROLE_GROUP, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_GROW_AREA, NSAccessibilityGrowAreaRole },
- { AccessibilityNodeData::ROLE_HEADING, @"AXHeading" },
- { AccessibilityNodeData::ROLE_HELP_TAG, NSAccessibilityHelpTagRole },
- { AccessibilityNodeData::ROLE_HORIZONTAL_RULE, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_IGNORED, NSAccessibilityUnknownRole },
- { AccessibilityNodeData::ROLE_IMAGE, NSAccessibilityImageRole },
- { AccessibilityNodeData::ROLE_IMAGE_MAP, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_IMAGE_MAP_LINK, NSAccessibilityLinkRole },
- { AccessibilityNodeData::ROLE_INCREMENTOR, NSAccessibilityIncrementorRole },
- { AccessibilityNodeData::ROLE_LABEL, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_LANDMARK_APPLICATION,
- NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_LANDMARK_BANNER, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_LANDMARK_COMPLEMENTARY,
- NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_LANDMARK_CONTENTINFO,
- NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_LANDMARK_MAIN, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_LANDMARK_NAVIGATION,
- NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_LANDMARK_SEARCH, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_LINK, NSAccessibilityLinkRole },
- { AccessibilityNodeData::ROLE_LIST, NSAccessibilityListRole },
- { AccessibilityNodeData::ROLE_LIST_ITEM, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_LIST_MARKER, @"AXListMarker" },
- { AccessibilityNodeData::ROLE_LISTBOX, NSAccessibilityListRole },
- { AccessibilityNodeData::ROLE_LISTBOX_OPTION,
- NSAccessibilityStaticTextRole },
- { AccessibilityNodeData::ROLE_LOG, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_MARQUEE, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_MATH, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_MATTE, NSAccessibilityMatteRole },
- { AccessibilityNodeData::ROLE_MENU, NSAccessibilityMenuRole },
- { AccessibilityNodeData::ROLE_MENU_BAR, NSAccessibilityMenuBarRole },
- { AccessibilityNodeData::ROLE_MENU_ITEM, NSAccessibilityMenuItemRole },
- { AccessibilityNodeData::ROLE_MENU_BUTTON, NSAccessibilityButtonRole },
- { AccessibilityNodeData::ROLE_MENU_LIST_OPTION,
- NSAccessibilityMenuItemRole },
- { AccessibilityNodeData::ROLE_MENU_LIST_POPUP, NSAccessibilityUnknownRole },
- { AccessibilityNodeData::ROLE_NOTE, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_OUTLINE, NSAccessibilityOutlineRole },
- { AccessibilityNodeData::ROLE_PARAGRAPH, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_POPUP_BUTTON,
- NSAccessibilityPopUpButtonRole },
- { AccessibilityNodeData::ROLE_PRESENTATIONAL, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_PROGRESS_INDICATOR,
- NSAccessibilityProgressIndicatorRole },
- { AccessibilityNodeData::ROLE_RADIO_BUTTON,
- NSAccessibilityRadioButtonRole },
- { AccessibilityNodeData::ROLE_RADIO_GROUP, NSAccessibilityRadioGroupRole },
- { AccessibilityNodeData::ROLE_REGION, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_ROOT_WEB_AREA, @"AXWebArea" },
- { AccessibilityNodeData::ROLE_ROW, NSAccessibilityRowRole },
- { AccessibilityNodeData::ROLE_ROW_HEADER, @"AXCell" },
- { AccessibilityNodeData::ROLE_RULER, NSAccessibilityRulerRole },
- { AccessibilityNodeData::ROLE_RULER_MARKER,
- NSAccessibilityRulerMarkerRole },
+ { 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,
+ 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,
+ 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 },
// TODO(dtseng): we don't correctly support the attributes for these roles.
- // { AccessibilityNodeData::ROLE_SCROLLAREA,
- // NSAccessibilityScrollAreaRole },
- { AccessibilityNodeData::ROLE_SCROLLBAR, NSAccessibilityScrollBarRole },
- { AccessibilityNodeData::ROLE_SHEET, NSAccessibilitySheetRole },
- { AccessibilityNodeData::ROLE_SLIDER, NSAccessibilitySliderRole },
- { AccessibilityNodeData::ROLE_SLIDER_THUMB,
- NSAccessibilityValueIndicatorRole },
- { AccessibilityNodeData::ROLE_SPIN_BUTTON, NSAccessibilitySliderRole },
- { AccessibilityNodeData::ROLE_SPLITTER, NSAccessibilitySplitterRole },
- { AccessibilityNodeData::ROLE_SPLIT_GROUP, NSAccessibilitySplitGroupRole },
- { AccessibilityNodeData::ROLE_STATIC_TEXT, NSAccessibilityStaticTextRole },
- { AccessibilityNodeData::ROLE_STATUS, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_SVG_ROOT, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_SYSTEM_WIDE, NSAccessibilityUnknownRole },
- { AccessibilityNodeData::ROLE_TAB, NSAccessibilityRadioButtonRole },
- { AccessibilityNodeData::ROLE_TAB_LIST, NSAccessibilityTabGroupRole },
- { AccessibilityNodeData::ROLE_TAB_PANEL, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_TABLE, NSAccessibilityTableRole },
- { AccessibilityNodeData::ROLE_TABLE_HEADER_CONTAINER,
- NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_TAB_GROUP_UNUSED,
- NSAccessibilityTabGroupRole },
- { AccessibilityNodeData::ROLE_TEXTAREA, NSAccessibilityTextAreaRole },
- { AccessibilityNodeData::ROLE_TEXT_FIELD, NSAccessibilityTextFieldRole },
- { AccessibilityNodeData::ROLE_TIMER, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_TOGGLE_BUTTON, NSAccessibilityButtonRole },
- { AccessibilityNodeData::ROLE_TOOLBAR, NSAccessibilityToolbarRole },
- { AccessibilityNodeData::ROLE_TOOLTIP, NSAccessibilityGroupRole },
- { AccessibilityNodeData::ROLE_TREE, NSAccessibilityOutlineRole },
- { AccessibilityNodeData::ROLE_TREE_GRID, NSAccessibilityTableRole },
- { AccessibilityNodeData::ROLE_TREE_ITEM, NSAccessibilityRowRole },
- { AccessibilityNodeData::ROLE_VALUE_INDICATOR,
- NSAccessibilityValueIndicatorRole },
- { AccessibilityNodeData::ROLE_WEBCORE_LINK, NSAccessibilityLinkRole },
- { AccessibilityNodeData::ROLE_WEB_AREA, @"AXWebArea" },
- { AccessibilityNodeData::ROLE_WINDOW, NSAccessibilityWindowRole },
+ // { 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 },
};
RoleMap role_map;
@@ -198,7 +173,7 @@ RoleMap BuildRoleMap() {
// A mapping of webkit roles to native roles.
NSString* NativeRoleFromAccessibilityNodeDataRole(
- const AccessibilityNodeData::Role& role) {
+ const WebKit::WebAXRole& role) {
CR_DEFINE_STATIC_LOCAL(RoleMap, web_accessibility_to_native_role,
(BuildRoleMap()));
RoleMap::iterator it = web_accessibility_to_native_role.find(role);
@@ -210,36 +185,32 @@ NSString* NativeRoleFromAccessibilityNodeDataRole(
RoleMap BuildSubroleMap() {
const MapEntry subroles[] = {
- { AccessibilityNodeData::ROLE_ALERT, @"AXApplicationAlert" },
- { AccessibilityNodeData::ROLE_ALERT_DIALOG, @"AXApplicationAlertDialog" },
- { AccessibilityNodeData::ROLE_ARTICLE, @"AXDocumentArticle" },
- { AccessibilityNodeData::ROLE_DEFINITION, @"AXDefinition" },
- { AccessibilityNodeData::ROLE_DESCRIPTION_LIST_DETAIL, @"AXDescription" },
- { AccessibilityNodeData::ROLE_DESCRIPTION_LIST_TERM, @"AXTerm" },
- { AccessibilityNodeData::ROLE_DIALOG, @"AXApplicationDialog" },
- { AccessibilityNodeData::ROLE_DOCUMENT, @"AXDocument" },
- { AccessibilityNodeData::ROLE_FOOTER, @"AXLandmarkContentInfo" },
- { AccessibilityNodeData::ROLE_LANDMARK_APPLICATION,
- @"AXLandmarkApplication" },
- { AccessibilityNodeData::ROLE_LANDMARK_BANNER, @"AXLandmarkBanner" },
- { AccessibilityNodeData::ROLE_LANDMARK_COMPLEMENTARY,
- @"AXLandmarkComplementary" },
- { AccessibilityNodeData::ROLE_LANDMARK_CONTENTINFO,
- @"AXLandmarkContentInfo" },
- { AccessibilityNodeData::ROLE_LANDMARK_MAIN, @"AXLandmarkMain" },
- { AccessibilityNodeData::ROLE_LANDMARK_NAVIGATION,
- @"AXLandmarkNavigation" },
- { AccessibilityNodeData::ROLE_LANDMARK_SEARCH, @"AXLandmarkSearch" },
- { AccessibilityNodeData::ROLE_LOG, @"AXApplicationLog" },
- { AccessibilityNodeData::ROLE_MARQUEE, @"AXApplicationMarquee" },
- { AccessibilityNodeData::ROLE_MATH, @"AXDocumentMath" },
- { AccessibilityNodeData::ROLE_NOTE, @"AXDocumentNote" },
- { AccessibilityNodeData::ROLE_REGION, @"AXDocumentRegion" },
- { AccessibilityNodeData::ROLE_STATUS, @"AXApplicationStatus" },
- { AccessibilityNodeData::ROLE_TAB_PANEL, @"AXTabPanel" },
- { AccessibilityNodeData::ROLE_TIMER, @"AXApplicationTimer" },
- { AccessibilityNodeData::ROLE_TOOLTIP, @"AXUserInterfaceTooltip" },
- { AccessibilityNodeData::ROLE_TREE_ITEM, NSAccessibilityOutlineRowSubrole },
+ { 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 },
};
RoleMap subrole_map;
@@ -250,7 +221,7 @@ RoleMap BuildSubroleMap() {
// A mapping of webkit roles to native subroles.
NSString* NativeSubroleFromAccessibilityNodeDataRole(
- const AccessibilityNodeData::Role& role) {
+ const WebKit::WebAXRole& role) {
CR_DEFINE_STATIC_LOCAL(RoleMap, web_accessibility_to_native_subrole,
(BuildSubroleMap()));
RoleMap::iterator it = web_accessibility_to_native_subrole.find(role);
@@ -353,34 +324,29 @@ NSDictionary* attributeToMethodNameMap = nil;
- (NSString*)accessKey {
return NSStringForStringAttribute(
- browserAccessibility_->string_attributes(),
- AccessibilityNodeData::ATTR_ACCESS_KEY);
+ browserAccessibility_, AccessibilityNodeData::ATTR_ACCESS_KEY);
}
- (NSNumber*)ariaAtomic {
- bool boolValue = false;
- browserAccessibility_->GetBoolAttribute(
- AccessibilityNodeData::ATTR_LIVE_ATOMIC, &boolValue);
+ bool boolValue = browserAccessibility_->GetBoolAttribute(
+ AccessibilityNodeData::ATTR_LIVE_ATOMIC);
return [NSNumber numberWithBool:boolValue];
}
- (NSNumber*)ariaBusy {
- bool boolValue = false;
- browserAccessibility_->GetBoolAttribute(
- AccessibilityNodeData::ATTR_LIVE_BUSY, &boolValue);
+ bool boolValue = browserAccessibility_->GetBoolAttribute(
+ AccessibilityNodeData::ATTR_LIVE_BUSY);
return [NSNumber numberWithBool:boolValue];
}
- (NSString*)ariaLive {
return NSStringForStringAttribute(
- browserAccessibility_->string_attributes(),
- AccessibilityNodeData::ATTR_LIVE_STATUS);
+ browserAccessibility_, AccessibilityNodeData::ATTR_LIVE_STATUS);
}
- (NSString*)ariaRelevant {
return NSStringForStringAttribute(
- browserAccessibility_->string_attributes(),
- AccessibilityNodeData::ATTR_LIVE_RELEVANT);
+ browserAccessibility_, AccessibilityNodeData::ATTR_LIVE_RELEVANT);
}
// Returns an array of BrowserAccessibilityCocoa objects, representing the
@@ -401,10 +367,11 @@ NSDictionary* attributeToMethodNameMap = nil;
}
// Also, add indirect children (if any).
- for (uint32 i = 0;
- i < browserAccessibility_->indirect_child_ids().size();
- ++i) {
- int32 child_id = browserAccessibility_->indirect_child_ids()[i];
+ const std::vector<int32>& indirectChildIds =
+ browserAccessibility_->GetIntListAttribute(
+ AccessibilityNodeData::ATTR_INDIRECT_CHILD_IDS);
+ for (uint32 i = 0; i < indirectChildIds.size(); ++i) {
+ int32 child_id = indirectChildIds[i];
BrowserAccessibility* child =
browserAccessibility_->manager()->GetFromRendererID(child_id);
@@ -430,26 +397,27 @@ NSDictionary* attributeToMethodNameMap = nil;
}
- (NSArray*)columnHeaders {
- if ([self internalRole] != AccessibilityNodeData::ROLE_TABLE &&
- [self internalRole] != AccessibilityNodeData::ROLE_GRID) {
+ if ([self internalRole] != WebKit::WebAXRoleTable &&
+ [self internalRole] != WebKit::WebAXRoleGrid) {
return nil;
}
NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease];
const std::vector<int32>& uniqueCellIds =
- browserAccessibility_->unique_cell_ids();
+ browserAccessibility_->GetIntListAttribute(
+ AccessibilityNodeData::ATTR_UNIQUE_CELL_IDS);
for (size_t i = 0; i < uniqueCellIds.size(); ++i) {
int id = uniqueCellIds[i];
BrowserAccessibility* cell =
browserAccessibility_->manager()->GetFromRendererID(id);
- if (cell && cell->role() == AccessibilityNodeData::ROLE_COLUMN_HEADER)
+ if (cell && cell->role() == WebKit::WebAXRoleColumnHeader)
[ret addObject:cell->ToBrowserAccessibilityCocoa()];
}
return ret;
}
- (NSValue*)columnIndexRange {
- if ([self internalRole] != AccessibilityNodeData::ROLE_CELL)
+ if ([self internalRole] != WebKit::WebAXRoleCell)
return nil;
int column = -1;
@@ -473,44 +441,43 @@ NSDictionary* attributeToMethodNameMap = nil;
}
- (NSString*)description {
- const std::map<StringAttribute, string16>& attributes =
- browserAccessibility_->string_attributes();
- std::map<StringAttribute, string16>::const_iterator iter =
- attributes.find(AccessibilityNodeData::ATTR_DESCRIPTION);
- if (iter != attributes.end())
- return base::SysUTF16ToNSString(iter->second);
+ std::string description;
+ if (browserAccessibility_->GetStringAttribute(
+ AccessibilityNodeData::ATTR_DESCRIPTION, &description)) {
+ return base::SysUTF8ToNSString(description);
+ }
// If the role is anything other than an image, or if there's
// a title or title UI element, just return an empty string.
if (![[self role] isEqualToString:NSAccessibilityImageRole])
return @"";
- if (!browserAccessibility_->name().empty())
+ if (browserAccessibility_->HasStringAttribute(
+ AccessibilityNodeData::ATTR_NAME)) {
return @"";
+ }
if ([self titleUIElement])
return @"";
// The remaining case is an image where there's no other title.
// Return the base part of the filename as the description.
- iter = attributes.find(AccessibilityNodeData::ATTR_URL);
- if (iter != attributes.end()) {
- string16 filename = iter->second;
+ std::string url;
+ if (browserAccessibility_->GetStringAttribute(
+ AccessibilityNodeData::ATTR_URL, &url)) {
// Given a url like http://foo.com/bar/baz.png, just return the
// base name, e.g., "baz.png".
- size_t leftIndex = filename.size();
- while (leftIndex > 0 && filename[leftIndex - 1] != '/')
- leftIndex--;
- string16 basename = filename.substr(leftIndex);
-
- return base::SysUTF16ToNSString(basename);
+ size_t leftIndex = url.rfind('/');
+ std::string basename =
+ leftIndex != std::string::npos ? url.substr(leftIndex) : url;
+ return base::SysUTF8ToNSString(basename);
}
return @"";
}
- (NSNumber*)disclosing {
- if ([self internalRole] == AccessibilityNodeData::ROLE_TREE_ITEM) {
+ if ([self internalRole] == WebKit::WebAXRoleTreeItem) {
return [NSNumber numberWithBool:
- GetState(browserAccessibility_, AccessibilityNodeData::STATE_EXPANDED)];
+ GetState(browserAccessibility_, WebKit::WebAXStateExpanded)];
} else {
return nil;
}
@@ -523,12 +490,11 @@ NSDictionary* attributeToMethodNameMap = nil;
}
- (NSNumber*)disclosureLevel {
- AccessibilityNodeData::Role role = [self internalRole];
- if (role == AccessibilityNodeData::ROLE_ROW ||
- role == AccessibilityNodeData::ROLE_TREE_ITEM) {
- int level = 0;
- browserAccessibility_->GetIntAttribute(
- AccessibilityNodeData::ATTR_HIERARCHICAL_LEVEL, &level);
+ WebKit::WebAXRole role = [self internalRole];
+ if (role == WebKit::WebAXRoleRow ||
+ role == WebKit::WebAXRoleTreeItem) {
+ int level = browserAccessibility_->GetIntAttribute(
+ AccessibilityNodeData::ATTR_HIERARCHICAL_LEVEL);
// Mac disclosureLevel is 0-based, but web levels are 1-based.
if (level > 0)
level--;
@@ -545,8 +511,7 @@ NSDictionary* attributeToMethodNameMap = nil;
- (NSNumber*)enabled {
return [NSNumber numberWithBool:
- !GetState(browserAccessibility_,
- AccessibilityNodeData::STATE_UNAVAILABLE)];
+ GetState(browserAccessibility_, WebKit::WebAXStateEnabled)];
}
- (NSNumber*)focused {
@@ -558,14 +523,14 @@ NSDictionary* attributeToMethodNameMap = nil;
- (id)header {
int headerElementId = -1;
- if ([self internalRole] == AccessibilityNodeData::ROLE_TABLE ||
- [self internalRole] == AccessibilityNodeData::ROLE_GRID) {
+ if ([self internalRole] == WebKit::WebAXRoleTable ||
+ [self internalRole] == WebKit::WebAXRoleGrid) {
browserAccessibility_->GetIntAttribute(
AccessibilityNodeData::ATTR_TABLE_HEADER_ID, &headerElementId);
- } else if ([self internalRole] == AccessibilityNodeData::ROLE_COLUMN) {
+ } else if ([self internalRole] == WebKit::WebAXRoleColumn) {
browserAccessibility_->GetIntAttribute(
AccessibilityNodeData::ATTR_TABLE_COLUMN_HEADER_ID, &headerElementId);
- } else if ([self internalRole] == AccessibilityNodeData::ROLE_ROW) {
+ } else if ([self internalRole] == WebKit::WebAXRoleRow) {
browserAccessibility_->GetIntAttribute(
AccessibilityNodeData::ATTR_TABLE_ROW_HEADER_ID, &headerElementId);
}
@@ -581,23 +546,18 @@ NSDictionary* attributeToMethodNameMap = nil;
- (NSString*)help {
return NSStringForStringAttribute(
- browserAccessibility_->string_attributes(),
- AccessibilityNodeData::ATTR_HELP);
+ browserAccessibility_, AccessibilityNodeData::ATTR_HELP);
}
- (NSNumber*)index {
- if ([self internalRole] == AccessibilityNodeData::ROLE_COLUMN) {
- int columnIndex;
- if (browserAccessibility_->GetIntAttribute(
- AccessibilityNodeData::ATTR_TABLE_COLUMN_INDEX, &columnIndex)) {
- return [NSNumber numberWithInt:columnIndex];
- }
- } else if ([self internalRole] == AccessibilityNodeData::ROLE_ROW) {
- int rowIndex;
- if (browserAccessibility_->GetIntAttribute(
- AccessibilityNodeData::ATTR_TABLE_ROW_INDEX, &rowIndex)) {
- return [NSNumber numberWithInt:rowIndex];
- }
+ if ([self internalRole] == WebKit::WebAXRoleColumn) {
+ int columnIndex = browserAccessibility_->GetIntAttribute(
+ AccessibilityNodeData::ATTR_TABLE_COLUMN_INDEX);
+ return [NSNumber numberWithInt:columnIndex];
+ } else if ([self internalRole] == WebKit::WebAXRoleRow) {
+ int rowIndex = browserAccessibility_->GetIntAttribute(
+ AccessibilityNodeData::ATTR_TABLE_ROW_INDEX);
+ return [NSNumber numberWithInt:rowIndex];
}
return nil;
@@ -626,33 +586,30 @@ NSDictionary* attributeToMethodNameMap = nil;
}
- (NSNumber*)loadingProgress {
- float floatValue = 0.0;
- browserAccessibility_->GetFloatAttribute(
- AccessibilityNodeData::ATTR_DOC_LOADING_PROGRESS, &floatValue);
+ float floatValue = browserAccessibility_->GetFloatAttribute(
+ AccessibilityNodeData::ATTR_DOC_LOADING_PROGRESS);
return [NSNumber numberWithFloat:floatValue];
}
- (NSNumber*)maxValue {
- float floatValue = 0.0;
- browserAccessibility_->GetFloatAttribute(
- AccessibilityNodeData::ATTR_MAX_VALUE_FOR_RANGE, &floatValue);
+ float floatValue = browserAccessibility_->GetFloatAttribute(
+ AccessibilityNodeData::ATTR_MAX_VALUE_FOR_RANGE);
return [NSNumber numberWithFloat:floatValue];
}
- (NSNumber*)minValue {
- float floatValue = 0.0;
- browserAccessibility_->GetFloatAttribute(
- AccessibilityNodeData::ATTR_MIN_VALUE_FOR_RANGE, &floatValue);
+ float floatValue = browserAccessibility_->GetFloatAttribute(
+ AccessibilityNodeData::ATTR_MIN_VALUE_FOR_RANGE);
return [NSNumber numberWithFloat:floatValue];
}
- (NSString*)orientation {
// We present a spin button as a vertical slider, with a role description
// of "spin button".
- if ([self internalRole] == AccessibilityNodeData::ROLE_SPIN_BUTTON)
+ if ([self internalRole] == WebKit::WebAXRoleSpinButton)
return NSAccessibilityVerticalOrientationValue;
- if (GetState(browserAccessibility_, AccessibilityNodeData::STATE_VERTICAL))
+ if (GetState(browserAccessibility_, WebKit::WebAXStateVertical))
return NSAccessibilityVerticalOrientationValue;
else
return NSAccessibilityHorizontalOrientationValue;
@@ -690,18 +647,23 @@ NSDictionary* attributeToMethodNameMap = nil;
- (NSNumber*)required {
return [NSNumber numberWithBool:
- GetState(browserAccessibility_, AccessibilityNodeData::STATE_REQUIRED)];
+ GetState(browserAccessibility_, WebKit::WebAXStateRequired)];
}
// Returns an enum indicating the role from browserAccessibility_.
-- (AccessibilityNodeData::Role)internalRole {
- return static_cast<AccessibilityNodeData::Role>(
- browserAccessibility_->role());
+- (WebKit::WebAXRole)internalRole {
+ return static_cast<WebKit::WebAXRole>(browserAccessibility_->role());
}
// Returns a string indicating the NSAccessibility role of this object.
- (NSString*)role {
- return NativeRoleFromAccessibilityNodeDataRole([self internalRole]);
+ WebKit::WebAXRole role = [self internalRole];
+ if (role == WebKit::WebAXRoleCanvas &&
+ browserAccessibility_->GetBoolAttribute(
+ AccessibilityNodeData::ATTR_CANVAS_HAS_FALLBACK)) {
+ return NSAccessibilityGroupRole;
+ }
+ return NativeRoleFromAccessibilityNodeDataRole(role);
}
// Returns a string indicating the role description of this object.
@@ -728,27 +690,23 @@ NSDictionary* attributeToMethodNameMap = nil;
if ([role isEqualToString:NSAccessibilityGroupRole] ||
[role isEqualToString:NSAccessibilityRadioButtonRole]) {
- const std::vector<std::pair<string16, string16> >& htmlAttributes =
- browserAccessibility_->html_attributes();
- AccessibilityNodeData::Role browserAccessibilityRole = [self internalRole];
- if ((browserAccessibilityRole != AccessibilityNodeData::ROLE_GROUP &&
- browserAccessibilityRole != AccessibilityNodeData::ROLE_LIST_ITEM) ||
- browserAccessibilityRole == AccessibilityNodeData::ROLE_TAB) {
- for (size_t i = 0; i < htmlAttributes.size(); ++i) {
- const std::pair<string16, string16>& htmlAttribute = htmlAttributes[i];
- if (htmlAttribute.first == ASCIIToUTF16("role")) {
- // TODO(dtseng): This is not localized; see crbug/84814.
- return base::SysUTF16ToNSString(htmlAttribute.second);
- }
+ std::string role;
+ if (browserAccessibility_->GetHtmlAttribute("role", &role)) {
+ WebKit::WebAXRole internalRole = [self internalRole];
+ if ((internalRole != WebKit::WebAXRoleGroup &&
+ internalRole != WebKit::WebAXRoleListItem) ||
+ internalRole == WebKit::WebAXRoleTab) {
+ // TODO(dtseng): This is not localized; see crbug/84814.
+ return base::SysUTF8ToNSString(role);
}
}
}
switch([self internalRole]) {
- case AccessibilityNodeData::ROLE_FOOTER:
+ case WebKit::WebAXRoleFooter:
return base::SysUTF16ToNSString(content_client->GetLocalizedString(
IDS_AX_ROLE_FOOTER));
- case AccessibilityNodeData::ROLE_SPIN_BUTTON:
+ case WebKit::WebAXRoleSpinButton:
// This control is similar to what VoiceOver calls a "stepper".
return base::SysUTF16ToNSString(content_client->GetLocalizedString(
IDS_AX_ROLE_STEPPER));
@@ -760,26 +718,27 @@ NSDictionary* attributeToMethodNameMap = nil;
}
- (NSArray*)rowHeaders {
- if ([self internalRole] != AccessibilityNodeData::ROLE_TABLE &&
- [self internalRole] != AccessibilityNodeData::ROLE_GRID) {
+ if ([self internalRole] != WebKit::WebAXRoleTable &&
+ [self internalRole] != WebKit::WebAXRoleGrid) {
return nil;
}
NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease];
const std::vector<int32>& uniqueCellIds =
- browserAccessibility_->unique_cell_ids();
+ browserAccessibility_->GetIntListAttribute(
+ AccessibilityNodeData::ATTR_UNIQUE_CELL_IDS);
for (size_t i = 0; i < uniqueCellIds.size(); ++i) {
int id = uniqueCellIds[i];
BrowserAccessibility* cell =
browserAccessibility_->manager()->GetFromRendererID(id);
- if (cell && cell->role() == AccessibilityNodeData::ROLE_ROW_HEADER)
+ if (cell && cell->role() == WebKit::WebAXRoleRowHeader)
[ret addObject:cell->ToBrowserAccessibilityCocoa()];
}
return ret;
}
- (NSValue*)rowIndexRange {
- if ([self internalRole] != AccessibilityNodeData::ROLE_CELL)
+ if ([self internalRole] != WebKit::WebAXRoleCell)
return nil;
int row = -1;
@@ -796,15 +755,16 @@ NSDictionary* attributeToMethodNameMap = nil;
- (NSArray*)rows {
NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease];
- if ([self internalRole] == AccessibilityNodeData::ROLE_TABLE||
- [self internalRole] == AccessibilityNodeData::ROLE_GRID) {
+ if ([self internalRole] == WebKit::WebAXRoleTable||
+ [self internalRole] == WebKit::WebAXRoleGrid) {
for (BrowserAccessibilityCocoa* child in [self children]) {
if ([[child role] isEqualToString:NSAccessibilityRowRole])
[ret addObject:child];
}
- } else if ([self internalRole] == AccessibilityNodeData::ROLE_COLUMN) {
+ } else if ([self internalRole] == WebKit::WebAXRoleColumn) {
const std::vector<int32>& indirectChildIds =
- browserAccessibility_->indirect_child_ids();
+ browserAccessibility_->GetIntListAttribute(
+ AccessibilityNodeData::ATTR_INDIRECT_CHILD_IDS);
for (uint32 i = 0; i < indirectChildIds.size(); ++i) {
int id = indirectChildIds[i];
BrowserAccessibility* rowElement =
@@ -825,17 +785,16 @@ NSDictionary* attributeToMethodNameMap = nil;
// Returns a subrole based upon the role.
- (NSString*) subrole {
- AccessibilityNodeData::Role browserAccessibilityRole = [self internalRole];
- if (browserAccessibilityRole == AccessibilityNodeData::ROLE_TEXT_FIELD &&
- GetState(browserAccessibility_, AccessibilityNodeData::STATE_PROTECTED)) {
+ WebKit::WebAXRole browserAccessibilityRole = [self internalRole];
+ if (browserAccessibilityRole == WebKit::WebAXRoleTextField &&
+ GetState(browserAccessibility_, WebKit::WebAXStateProtected)) {
return @"AXSecureTextField";
}
NSString* htmlTag = NSStringForStringAttribute(
- browserAccessibility_->string_attributes(),
- AccessibilityNodeData::ATTR_HTML_TAG);
+ browserAccessibility_, AccessibilityNodeData::ATTR_HTML_TAG);
- if (browserAccessibilityRole == AccessibilityNodeData::ROLE_LIST) {
+ if (browserAccessibilityRole == WebKit::WebAXRoleList) {
if ([htmlTag isEqualToString:@"ul"] ||
[htmlTag isEqualToString:@"ol"]) {
return @"AXContentList";
@@ -851,7 +810,7 @@ NSDictionary* attributeToMethodNameMap = nil;
- (NSArray*)tabs {
NSMutableArray* tabSubtree = [[[NSMutableArray alloc] init] autorelease];
- if ([self internalRole] == AccessibilityNodeData::ROLE_TAB)
+ if ([self internalRole] == WebKit::WebAXRoleTab)
[tabSubtree addObject:self];
for (uint i=0; i < [[self children] count]; ++i) {
@@ -864,7 +823,8 @@ NSDictionary* attributeToMethodNameMap = nil;
}
- (NSString*)title {
- return base::SysUTF16ToNSString(browserAccessibility_->name());
+ return NSStringForStringAttribute(
+ browserAccessibility_, AccessibilityNodeData::ATTR_NAME);
}
- (id)titleUIElement {
@@ -884,9 +844,7 @@ NSDictionary* attributeToMethodNameMap = nil;
[[self role] isEqualToString:@"AXWebArea"] ?
AccessibilityNodeData::ATTR_DOC_URL :
AccessibilityNodeData::ATTR_URL;
- return NSStringForStringAttribute(
- browserAccessibility_->string_attributes(),
- urlAttribute);
+ return NSStringForStringAttribute(browserAccessibility_, urlAttribute);
}
- (id)value {
@@ -895,7 +853,7 @@ NSDictionary* attributeToMethodNameMap = nil;
// to approximate Cocoa ax behavior best as we can.
NSString* role = [self role];
if ([role isEqualToString:@"AXHeading"]) {
- int level;
+ int level = 0;
if (browserAccessibility_->GetIntAttribute(
AccessibilityNodeData::ATTR_HIERARCHICAL_LEVEL, &level)) {
return [NSNumber numberWithInt:level];
@@ -907,17 +865,16 @@ NSDictionary* attributeToMethodNameMap = nil;
[role isEqualToString:NSAccessibilityRadioButtonRole]) {
int value = 0;
value = GetState(
- browserAccessibility_, AccessibilityNodeData::STATE_CHECKED) ? 1 : 0;
+ browserAccessibility_, WebKit::WebAXStateChecked) ? 1 : 0;
value = GetState(
- browserAccessibility_, AccessibilityNodeData::STATE_SELECTED) ?
+ browserAccessibility_, WebKit::WebAXStateSelected) ?
1 :
value;
- bool mixed = false;
- browserAccessibility_->GetBoolAttribute(
- AccessibilityNodeData::ATTR_BUTTON_MIXED, &mixed);
- if (mixed)
+ if (browserAccessibility_->GetBoolAttribute(
+ AccessibilityNodeData::ATTR_BUTTON_MIXED)) {
value = 2;
+ }
return [NSNumber numberWithInt:value];
} else if ([role isEqualToString:NSAccessibilityProgressIndicatorRole] ||
[role isEqualToString:NSAccessibilitySliderRole] ||
@@ -928,26 +885,24 @@ NSDictionary* attributeToMethodNameMap = nil;
return [NSNumber numberWithFloat:floatValue];
}
} else if ([role isEqualToString:NSAccessibilityColorWellRole]) {
- int r, g, b;
- browserAccessibility_->GetIntAttribute(
- AccessibilityNodeData::ATTR_COLOR_VALUE_RED, &r);
- browserAccessibility_->GetIntAttribute(
- AccessibilityNodeData::ATTR_COLOR_VALUE_GREEN, &g);
- browserAccessibility_->GetIntAttribute(
- AccessibilityNodeData::ATTR_COLOR_VALUE_BLUE, &b);
+ int r = browserAccessibility_->GetIntAttribute(
+ AccessibilityNodeData::ATTR_COLOR_VALUE_RED);
+ int g = browserAccessibility_->GetIntAttribute(
+ AccessibilityNodeData::ATTR_COLOR_VALUE_GREEN);
+ int b = browserAccessibility_->GetIntAttribute(
+ AccessibilityNodeData::ATTR_COLOR_VALUE_BLUE);
// This string matches the one returned by a native Mac color well.
return [NSString stringWithFormat:@"rgb %7.5f %7.5f %7.5f 1",
r / 255., g / 255., b / 255.];
}
- return base::SysUTF16ToNSString(browserAccessibility_->value());
+ return NSStringForStringAttribute(
+ browserAccessibility_, AccessibilityNodeData::ATTR_VALUE);
}
- (NSString*)valueDescription {
- if (!browserAccessibility_->value().empty())
- return base::SysUTF16ToNSString(browserAccessibility_->value());
- else
- return nil;
+ return NSStringForStringAttribute(
+ browserAccessibility_, AccessibilityNodeData::ATTR_VALUE);
}
- (NSValue*)visibleCharacterRange {
@@ -958,7 +913,8 @@ NSDictionary* attributeToMethodNameMap = nil;
- (NSArray*)visibleCells {
NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease];
const std::vector<int32>& uniqueCellIds =
- browserAccessibility_->unique_cell_ids();
+ browserAccessibility_->GetIntListAttribute(
+ AccessibilityNodeData::ATTR_UNIQUE_CELL_IDS);
for (size_t i = 0; i < uniqueCellIds.size(); ++i) {
int id = uniqueCellIds[i];
BrowserAccessibility* cell =
@@ -979,7 +935,7 @@ NSDictionary* attributeToMethodNameMap = nil;
- (NSNumber*)visited {
return [NSNumber numberWithBool:
- GetState(browserAccessibility_, AccessibilityNodeData::STATE_TRAVERSED)];
+ GetState(browserAccessibility_, WebKit::WebAXStateVisited)];
}
- (id)window {
@@ -1013,7 +969,8 @@ NSDictionary* attributeToMethodNameMap = nil;
if ([attribute isEqualToString:
NSAccessibilityInsertionPointLineNumberAttribute]) {
const std::vector<int32>& line_breaks =
- browserAccessibility_->line_breaks();
+ browserAccessibility_->GetIntListAttribute(
+ AccessibilityNodeData::ATTR_LINE_BREAKS);
for (int i = 0; i < static_cast<int>(line_breaks.size()); ++i) {
if (line_breaks[i] > selStart)
return [NSNumber numberWithInt:i];
@@ -1021,8 +978,9 @@ NSDictionary* attributeToMethodNameMap = nil;
return [NSNumber numberWithInt:static_cast<int>(line_breaks.size())];
}
if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute]) {
- return base::SysUTF16ToNSString(browserAccessibility_->value().substr(
- selStart, selLength));
+ std::string value = browserAccessibility_->GetStringAttribute(
+ AccessibilityNodeData::ATTR_VALUE);
+ return base::SysUTF8ToNSString(value.substr(selStart, selLength));
}
if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) {
return [NSValue valueWithRange:NSMakeRange(selStart, selLength)];
@@ -1038,14 +996,17 @@ NSDictionary* attributeToMethodNameMap = nil;
if (!browserAccessibility_)
return nil;
- const std::vector<int32>& line_breaks = browserAccessibility_->line_breaks();
+ const std::vector<int32>& line_breaks =
+ browserAccessibility_->GetIntListAttribute(
+ AccessibilityNodeData::ATTR_LINE_BREAKS);
int len = static_cast<int>(browserAccessibility_->value().size());
if ([attribute isEqualToString:
NSAccessibilityStringForRangeParameterizedAttribute]) {
NSRange range = [(NSValue*)parameter rangeValue];
- return base::SysUTF16ToNSString(
- browserAccessibility_->value().substr(range.location, range.length));
+ std::string value = browserAccessibility_->GetStringAttribute(
+ AccessibilityNodeData::ATTR_VALUE);
+ return base::SysUTF8ToNSString(value.substr(range.location, range.length));
}
if ([attribute isEqualToString:
@@ -1072,8 +1033,8 @@ NSDictionary* attributeToMethodNameMap = nil;
if ([attribute isEqualToString:
NSAccessibilityCellForColumnAndRowParameterizedAttribute]) {
- if ([self internalRole] != AccessibilityNodeData::ROLE_TABLE &&
- [self internalRole] != AccessibilityNodeData::ROLE_GRID) {
+ if ([self internalRole] != WebKit::WebAXRoleTable &&
+ [self internalRole] != WebKit::WebAXRoleGrid) {
return nil;
}
if (![parameter isKindOfClass:[NSArray self]])
@@ -1081,12 +1042,10 @@ NSDictionary* attributeToMethodNameMap = nil;
NSArray* array = parameter;
int column = [[array objectAtIndex:0] intValue];
int row = [[array objectAtIndex:1] intValue];
- int num_columns = 0;
- int num_rows = 0;
- browserAccessibility_->GetIntAttribute(
- AccessibilityNodeData::ATTR_TABLE_COLUMN_COUNT, &num_columns);
- browserAccessibility_->GetIntAttribute(
- AccessibilityNodeData::ATTR_TABLE_ROW_COUNT, &num_rows);
+ int num_columns = browserAccessibility_->GetIntAttribute(
+ AccessibilityNodeData::ATTR_TABLE_COLUMN_COUNT);
+ int num_rows = browserAccessibility_->GetIntAttribute(
+ AccessibilityNodeData::ATTR_TABLE_ROW_COUNT);
if (column < 0 || column >= num_columns ||
row < 0 || row >= num_rows) {
return nil;
@@ -1095,7 +1054,7 @@ NSDictionary* attributeToMethodNameMap = nil;
i < browserAccessibility_->child_count();
++i) {
BrowserAccessibility* child = browserAccessibility_->GetChild(i);
- if (child->role() != AccessibilityNodeData::ROLE_ROW)
+ if (child->role() != WebKit::WebAXRoleRow)
continue;
int rowIndex;
if (!child->GetIntAttribute(
@@ -1110,7 +1069,7 @@ NSDictionary* attributeToMethodNameMap = nil;
j < child->child_count();
++j) {
BrowserAccessibility* cell = child->GetChild(j);
- if (cell->role() != AccessibilityNodeData::ROLE_CELL)
+ if (cell->role() != WebKit::WebAXRoleCell)
continue;
int colIndex;
if (!cell->GetIntAttribute(
@@ -1335,16 +1294,15 @@ NSDictionary* attributeToMethodNameMap = nil;
}
// Live regions.
- string16 s;
- if (browserAccessibility_->GetStringAttribute(
- AccessibilityNodeData::ATTR_LIVE_STATUS, &s)) {
+ if (browserAccessibility_->HasStringAttribute(
+ AccessibilityNodeData::ATTR_LIVE_STATUS)) {
[ret addObjectsFromArray:[NSArray arrayWithObjects:
@"AXARIALive",
@"AXARIARelevant",
nil]];
}
- if (browserAccessibility_->GetStringAttribute(
- AccessibilityNodeData::ATTR_CONTAINER_LIVE_STATUS, &s)) {
+ if (browserAccessibility_->HasStringAttribute(
+ AccessibilityNodeData::ATTR_CONTAINER_LIVE_STATUS)) {
[ret addObjectsFromArray:[NSArray arrayWithObjects:
@"AXARIAAtomic",
@"AXARIABusy",
@@ -1352,9 +1310,8 @@ NSDictionary* attributeToMethodNameMap = nil;
}
// Title UI Element.
- int i;
- if (browserAccessibility_->GetIntAttribute(
- AccessibilityNodeData::ATTR_TITLE_UI_ELEMENT, &i)) {
+ if (browserAccessibility_->HasIntAttribute(
+ AccessibilityNodeData::ATTR_TITLE_UI_ELEMENT)) {
[ret addObjectsFromArray:[NSArray arrayWithObjects:
NSAccessibilityTitleUIElementAttribute,
nil]];
@@ -1385,12 +1342,10 @@ NSDictionary* attributeToMethodNameMap = nil;
if ([attribute isEqualToString:NSAccessibilityFocusedAttribute])
return GetState(browserAccessibility_,
- AccessibilityNodeData::STATE_FOCUSABLE);
+ WebKit::WebAXStateFocusable);
if ([attribute isEqualToString:NSAccessibilityValueAttribute]) {
- bool canSetValue = false;
- browserAccessibility_->GetBoolAttribute(
- AccessibilityNodeData::ATTR_CAN_SET_VALUE, &canSetValue);
- return canSetValue;
+ return browserAccessibility_->GetBoolAttribute(
+ AccessibilityNodeData::ATTR_CAN_SET_VALUE);
}
if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute] &&
([[self role] isEqualToString:NSAccessibilityTextFieldRole] ||
diff --git a/chromium/content/browser/accessibility/browser_accessibility_gtk.cc b/chromium/content/browser/accessibility/browser_accessibility_gtk.cc
index 50364282b3d..faf4c82e307 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_gtk.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_gtk.cc
@@ -178,7 +178,8 @@ static const gchar* browser_accessibility_get_name(AtkObject* atk_object) {
BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(atk_object);
if (!obj)
return NULL;
- return obj->atk_acc_name().c_str();
+
+ return obj->GetStringAttribute(AccessibilityNodeData::ATTR_NAME).c_str();
}
static const gchar* browser_accessibility_get_description(
@@ -186,7 +187,9 @@ static const gchar* browser_accessibility_get_description(
BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(atk_object);
if (!obj)
return NULL;
- return obj->atk_acc_description().c_str();
+
+ return obj->GetStringAttribute(
+ AccessibilityNodeData::ATTR_DESCRIPTION).c_str();
}
static AtkObject* browser_accessibility_get_parent(AtkObject* atk_object) {
@@ -247,11 +250,11 @@ static AtkStateSet* browser_accessibility_ref_state_set(AtkObject* atk_object) {
ref_state_set(atk_object);
int32 state = obj->state();
- if (state & (1 << AccessibilityNodeData::STATE_FOCUSABLE))
+ if (state & (1 << WebKit::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 << AccessibilityNodeData::STATE_UNAVAILABLE)))
+ if (state & (1 << WebKit::WebAXStateEnabled))
atk_state_set_add_state(state_set, ATK_STATE_ENABLED);
return state_set;
@@ -356,9 +359,9 @@ static int GetInterfaceMaskFromObject(BrowserAccessibilityGtk* obj) {
interface_mask |= 1 << ATK_COMPONENT_INTERFACE;
int role = obj->role();
- if (role == AccessibilityNodeData::ROLE_PROGRESS_INDICATOR ||
- role == AccessibilityNodeData::ROLE_SCROLLBAR ||
- role == AccessibilityNodeData::ROLE_SLIDER) {
+ if (role == WebKit::WebAXRoleProgressIndicator ||
+ role == WebKit::WebAXRoleScrollBar ||
+ role == WebKit::WebAXRoleSlider) {
interface_mask |= 1 << ATK_VALUE_INTERFACE;
}
@@ -467,49 +470,40 @@ bool BrowserAccessibilityGtk::IsNative() const {
}
void BrowserAccessibilityGtk::InitRoleAndState() {
- atk_acc_name_ = UTF16ToUTF8(name());
-
- string16 description;
- GetStringAttribute(AccessibilityNodeData::ATTR_DESCRIPTION, &description);
- atk_acc_description_ = UTF16ToUTF8(description);
-
switch(role_) {
- case AccessibilityNodeData::ROLE_DOCUMENT:
- case AccessibilityNodeData::ROLE_ROOT_WEB_AREA:
- case AccessibilityNodeData::ROLE_WEB_AREA:
+ case WebKit::WebAXRoleDocument:
+ case WebKit::WebAXRoleRootWebArea:
+ case WebKit::WebAXRoleWebArea:
atk_role_ = ATK_ROLE_DOCUMENT_WEB;
break;
- case AccessibilityNodeData::ROLE_GROUP:
- case AccessibilityNodeData::ROLE_DIV:
+ case WebKit::WebAXRoleGroup:
+ case WebKit::WebAXRoleDiv:
atk_role_ = ATK_ROLE_SECTION;
break;
- case AccessibilityNodeData::ROLE_BUTTON:
+ case WebKit::WebAXRoleButton:
atk_role_ = ATK_ROLE_PUSH_BUTTON;
break;
- case AccessibilityNodeData::ROLE_CHECKBOX:
+ case WebKit::WebAXRoleCheckBox:
atk_role_ = ATK_ROLE_CHECK_BOX;
break;
- case AccessibilityNodeData::ROLE_COMBO_BOX:
+ case WebKit::WebAXRoleComboBox:
atk_role_ = ATK_ROLE_COMBO_BOX;
break;
- case AccessibilityNodeData::ROLE_LINK:
+ case WebKit::WebAXRoleLink:
atk_role_ = ATK_ROLE_LINK;
break;
- case AccessibilityNodeData::ROLE_RADIO_BUTTON:
+ case WebKit::WebAXRoleRadioButton:
atk_role_ = ATK_ROLE_RADIO_BUTTON;
break;
- case AccessibilityNodeData::ROLE_STATIC_TEXT:
+ case WebKit::WebAXRoleStaticText:
atk_role_ = ATK_ROLE_TEXT;
break;
- case AccessibilityNodeData::ROLE_TEXTAREA:
+ case WebKit::WebAXRoleTextArea:
atk_role_ = ATK_ROLE_ENTRY;
break;
- case AccessibilityNodeData::ROLE_TEXT_FIELD:
+ case WebKit::WebAXRoleTextField:
atk_role_ = ATK_ROLE_ENTRY;
break;
- case AccessibilityNodeData::ROLE_WEBCORE_LINK:
- atk_role_ = ATK_ROLE_LINK;
- break;
default:
atk_role_ = ATK_ROLE_UNKNOWN;
break;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_gtk.h b/chromium/content/browser/accessibility/browser_accessibility_gtk.h
index 8f3a2e31e5b..c8895e358d1 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_gtk.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_gtk.h
@@ -68,8 +68,6 @@ class BrowserAccessibilityGtk : public BrowserAccessibility {
AtkObject* GetAtkObject() const;
AtkRole atk_role() { return atk_role_; }
- const std::string& atk_acc_name() { return atk_acc_name_; }
- const std::string& atk_acc_description() { return atk_acc_description_; }
// BrowserAccessibility methods.
virtual void PreInitialize() OVERRIDE;
@@ -83,8 +81,6 @@ class BrowserAccessibilityGtk : public BrowserAccessibility {
AtkObject* atk_object_;
AtkRole atk_role_;
- std::string atk_acc_name_;
- std::string atk_acc_description_;
int interface_mask_;
private:
diff --git a/chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm b/chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm
index 45137ec677a..d23d8e6a691 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm
@@ -67,25 +67,24 @@ class BrowserAccessibilityTest : public ui::CocoaTest {
root.id = 1000;
root.location.set_width(500);
root.location.set_height(100);
- root.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA;
- root.string_attributes[AccessibilityNodeData::ATTR_HELP] =
- ASCIIToUTF16("HelpText");
+ root.role = WebKit::WebAXRoleRootWebArea;
+ root.AddStringAttribute(AccessibilityNodeData::ATTR_HELP, "HelpText");
root.child_ids.push_back(1001);
root.child_ids.push_back(1002);
AccessibilityNodeData child1;
child1.id = 1001;
- child1.name = ASCIIToUTF16("Child1");
+ child1.SetName("Child1");
child1.location.set_width(250);
child1.location.set_height(100);
- child1.role = AccessibilityNodeData::ROLE_BUTTON;
+ child1.role = WebKit::WebAXRoleButton;
AccessibilityNodeData child2;
child2.id = 1002;
child2.location.set_x(250);
child2.location.set_width(250);
child2.location.set_height(100);
- child2.role = AccessibilityNodeData::ROLE_HEADING;
+ child2.role = WebKit::WebAXRoleHeading;
delegate_.reset([[MockAccessibilityDelegate alloc] init]);
manager_.reset(
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager.cc b/chromium/content/browser/accessibility/browser_accessibility_manager.cc
index 7def57459f9..2161fb11243 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 = AccessibilityNodeData::ROLE_ROOT_WEB_AREA;
+ empty_document.role = WebKit::WebAXRoleRootWebArea;
return empty_document;
}
@@ -93,7 +93,7 @@ void BrowserAccessibilityManager::GotFocus(bool touch_event_context) {
if (!focus_)
return;
- NotifyAccessibilityEvent(AccessibilityNotificationFocusChanged, focus_);
+ NotifyAccessibilityEvent(WebKit::WebAXEventFocus, focus_);
}
void BrowserAccessibilityManager::WasHidden() {
@@ -102,7 +102,7 @@ void BrowserAccessibilityManager::WasHidden() {
void BrowserAccessibilityManager::GotMouseDown() {
osk_state_ = OSK_ALLOWED_WITHIN_FOCUSED_OBJECT;
- NotifyAccessibilityEvent(AccessibilityNotificationFocusChanged, focus_);
+ NotifyAccessibilityEvent(WebKit::WebAXEventFocus, focus_);
}
bool BrowserAccessibilityManager::IsOSKAllowed(const gfx::Rect& bounds) {
@@ -124,24 +124,24 @@ void BrowserAccessibilityManager::RemoveNode(BrowserAccessibility* node) {
renderer_id_map_.erase(renderer_id);
}
-void BrowserAccessibilityManager::OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>& params) {
+void BrowserAccessibilityManager::OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>& params) {
for (uint32 index = 0; index < params.size(); index++) {
- const AccessibilityHostMsg_NotificationParams& param = params[index];
+ const AccessibilityHostMsg_EventParams& param = params[index];
// Update nodes that changed.
if (!UpdateNodes(param.nodes))
return;
// Find the node corresponding to the id that's the target of the
- // notification (which may not be the root of the update tree).
+ // event (which may not be the root of the update tree).
BrowserAccessibility* node = GetFromRendererID(param.id);
if (!node)
continue;
- int notification_type = param.notification_type;
- if (notification_type == AccessibilityNotificationFocusChanged ||
- notification_type == AccessibilityNotificationBlur) {
+ WebKit::WebAXEvent event_type = param.event_type;
+ if (event_type == WebKit::WebAXEventFocus ||
+ event_type == WebKit::WebAXEventBlur) {
SetFocus(node, false);
if (osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_HIDDEN &&
@@ -154,15 +154,15 @@ void BrowserAccessibilityManager::OnAccessibilityNotifications(
continue;
}
- // Send the notification event to the operating system.
- NotifyAccessibilityEvent(notification_type, node);
+ // Send the event event to the operating system.
+ NotifyAccessibilityEvent(event_type, node);
// Set initial focus when a page is loaded.
- if (notification_type == AccessibilityNotificationLoadComplete) {
+ if (event_type == WebKit::WebAXEventLoadComplete) {
if (!focus_)
SetFocus(root_, false);
if (!delegate_ || delegate_->HasFocus())
- NotifyAccessibilityEvent(AccessibilityNotificationFocusChanged, focus_);
+ NotifyAccessibilityEvent(WebKit::WebAXEventFocus, focus_);
}
}
}
@@ -333,16 +333,18 @@ bool BrowserAccessibilityManager::UpdateNode(const AccessibilityNodeData& src) {
// and this is a serious error.
BrowserAccessibility* instance = GetFromRendererID(src.id);
if (!instance) {
- if (src.role != AccessibilityNodeData::ROLE_ROOT_WEB_AREA)
+ if (src.role != WebKit::WebAXRoleRootWebArea)
return false;
instance = CreateNode(NULL, src.id, 0);
}
- if (src.bool_attributes.find(
- AccessibilityNodeData::ATTR_UPDATE_LOCATION_ONLY) !=
- src.bool_attributes.end()) {
- instance->SetLocation(src.location);
- return true;
+ // TODO(dmazzoni): avoid a linear scan here.
+ for (size_t i = 0; i < src.bool_attributes.size(); i++) {
+ if (src.bool_attributes[i].first ==
+ AccessibilityNodeData::ATTR_UPDATE_LOCATION_ONLY) {
+ instance->SetLocation(src.location);
+ return true;
+ }
}
// Update all of the node-specific data, like its role, state, name, etc.
@@ -398,7 +400,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 == AccessibilityNodeData::ROLE_ROOT_WEB_AREA &&
+ if (src.role == WebKit::WebAXRoleRootWebArea &&
(!root_ || root_->renderer_id() != src.id)) {
if (root_)
root_->Destroy();
@@ -408,9 +410,9 @@ bool BrowserAccessibilityManager::UpdateNode(const AccessibilityNodeData& src) {
}
// Keep track of what node is focused.
- if (src.role != AccessibilityNodeData::ROLE_ROOT_WEB_AREA &&
- src.role != AccessibilityNodeData::ROLE_WEB_AREA &&
- (src.state >> AccessibilityNodeData::STATE_FOCUSED & 1)) {
+ if (src.role != WebKit::WebAXRoleRootWebArea &&
+ src.role != WebKit::WebAXRoleWebArea &&
+ (src.state >> WebKit::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 5fac3e5e3f3..09439b2a4b5 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager.h
@@ -12,9 +12,10 @@
#include "build/build_config.h"
#include "content/common/accessibility_node_data.h"
#include "content/common/content_export.h"
+#include "third_party/WebKit/public/web/WebAXEnums.h"
#include "ui/gfx/native_widget_types.h"
-struct AccessibilityHostMsg_NotificationParams;
+struct AccessibilityHostMsg_EventParams;
namespace content {
class BrowserAccessibility;
@@ -65,12 +66,8 @@ class CONTENT_EXPORT BrowserAccessibilityManager {
static AccessibilityNodeData GetEmptyDocument();
- // Type is enum AccessibilityNotification.
- // We pass it as int so that we don't include the message declaration
- // header here.
virtual void NotifyAccessibilityEvent(
- int type,
- BrowserAccessibility* node) { }
+ WebKit::WebAXEvent event_type, BrowserAccessibility* node) { }
// Return a pointer to the root of the tree, does not make a new reference.
BrowserAccessibility* GetRoot();
@@ -126,8 +123,8 @@ class CONTENT_EXPORT BrowserAccessibilityManager {
// Called when the renderer process has notified us of about tree changes.
// Send a notification to MSAA clients of the change.
- void OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>& params);
+ void OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>& params);
#if defined(OS_WIN)
BrowserAccessibilityManagerWin* ToBrowserAccessibilityManagerWin();
@@ -146,7 +143,7 @@ class CONTENT_EXPORT BrowserAccessibilityManager {
virtual bool UseRootScrollOffsetsWhenComputingBounds();
// For testing only: update the given nodes as if they were
- // received from the renderer process in OnAccessibilityNotifications.
+ // received from the renderer process in OnAccessibilityEvents.
// Takes up to 7 nodes at once so tests don't need to create a vector
// each time.
void UpdateNodesForTesting(
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
index 2da686af934..2943c5cf4be 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
@@ -77,13 +77,13 @@ BrowserAccessibilityManagerAndroid::~BrowserAccessibilityManagerAndroid() {
AccessibilityNodeData BrowserAccessibilityManagerAndroid::GetEmptyDocument() {
AccessibilityNodeData empty_document;
empty_document.id = 0;
- empty_document.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA;
- empty_document.state = 1 << AccessibilityNodeData::STATE_READONLY;
+ empty_document.role = WebKit::WebAXRoleRootWebArea;
+ empty_document.state = 1 << WebKit::WebAXStateReadonly;
return empty_document;
}
void BrowserAccessibilityManagerAndroid::NotifyAccessibilityEvent(
- int type,
+ WebKit::WebAXEvent event_type,
BrowserAccessibility* node) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
@@ -96,27 +96,27 @@ void BrowserAccessibilityManagerAndroid::NotifyAccessibilityEvent(
Java_BrowserAccessibilityManager_handleContentChanged(
env, obj.obj(), node->renderer_id());
- switch (type) {
- case AccessibilityNotificationLoadComplete:
+ switch (event_type) {
+ case WebKit::WebAXEventLoadComplete:
Java_BrowserAccessibilityManager_handlePageLoaded(
env, obj.obj(), focus_->renderer_id());
break;
- case AccessibilityNotificationFocusChanged:
+ case WebKit::WebAXEventFocus:
Java_BrowserAccessibilityManager_handleFocusChanged(
env, obj.obj(), node->renderer_id());
break;
- case AccessibilityNotificationCheckStateChanged:
+ case WebKit::WebAXEventCheckedStateChanged:
Java_BrowserAccessibilityManager_handleCheckStateChanged(
env, obj.obj(), node->renderer_id());
break;
- case AccessibilityNotificationScrolledToAnchor:
+ case WebKit::WebAXEventScrolledToAnchor:
Java_BrowserAccessibilityManager_handleScrolledToAnchor(
env, obj.obj(), node->renderer_id());
break;
- case AccessibilityNotificationAlert:
+ case WebKit::WebAXEventAlert:
// An alert is a special case of live region. Fall through to the
// next case to handle it.
- case AccessibilityNotificationObjectShow: {
+ case WebKit::WebAXEventShow: {
// This event is fired when an object appears in a live region.
// Speak its text.
BrowserAccessibilityAndroid* android_node =
@@ -127,13 +127,13 @@ void BrowserAccessibilityManagerAndroid::NotifyAccessibilityEvent(
env, android_node->GetText()).obj());
break;
}
- case AccessibilityNotificationSelectedTextChanged:
+ case WebKit::WebAXEventSelectedTextChanged:
Java_BrowserAccessibilityManager_handleTextSelectionChanged(
env, obj.obj(), node->renderer_id());
break;
- case AccessibilityNotificationChildrenChanged:
- case AccessibilityNotificationTextChanged:
- case AccessibilityNotificationValueChanged:
+ case WebKit::WebAXEventChildrenChanged:
+ case WebKit::WebAXEventTextChanged:
+ case WebKit::WebAXEventValueChanged:
if (node->IsEditableText()) {
Java_BrowserAccessibilityManager_handleEditableTextChanged(
env, obj.obj(), node->renderer_id());
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_android.h b/chromium/content/browser/accessibility/browser_accessibility_manager_android.h
index 2a6c291bacb..056fe8dff6f 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_android.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_android.h
@@ -30,8 +30,8 @@ class CONTENT_EXPORT BrowserAccessibilityManagerAndroid
static AccessibilityNodeData GetEmptyDocument();
// Implementation of BrowserAccessibilityManager.
- virtual void NotifyAccessibilityEvent(int type,
- BrowserAccessibility* node) OVERRIDE;
+ virtual void NotifyAccessibilityEvent(
+ WebKit::WebAXEvent event_type, BrowserAccessibility* node) OVERRIDE;
// --------------------------------------------------------------------------
// Methods called from Java via JNI
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_gtk.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_gtk.cc
index 15191c6a35b..a6246c5e795 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_gtk.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_gtk.cc
@@ -38,24 +38,24 @@ BrowserAccessibilityManagerGtk::~BrowserAccessibilityManagerGtk() {
AccessibilityNodeData BrowserAccessibilityManagerGtk::GetEmptyDocument() {
AccessibilityNodeData empty_document;
empty_document.id = 0;
- empty_document.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA;
+ empty_document.role = WebKit::WebAXRoleRootWebArea;
empty_document.state =
- 1 << AccessibilityNodeData::STATE_READONLY;
+ 1 << WebKit::WebAXStateReadonly;
return empty_document;
}
void BrowserAccessibilityManagerGtk::NotifyAccessibilityEvent(
- int type,
+ WebKit::WebAXEvent event_type,
BrowserAccessibility* node) {
if (!node->IsNative())
return;
AtkObject* atk_object = node->ToBrowserAccessibilityGtk()->GetAtkObject();
- switch (type) {
- case AccessibilityNotificationChildrenChanged:
+ switch (event_type) {
+ case WebKit::WebAXEventChildrenChanged:
RecursivelySendChildrenChanged(GetRoot()->ToBrowserAccessibilityGtk());
break;
- case AccessibilityNotificationFocusChanged:
+ 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
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_gtk.h b/chromium/content/browser/accessibility/browser_accessibility_manager_gtk.h
index eedae7ca121..4c29d8d7955 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_gtk.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_gtk.h
@@ -27,8 +27,8 @@ class CONTENT_EXPORT BrowserAccessibilityManagerGtk
static AccessibilityNodeData GetEmptyDocument();
// BrowserAccessibilityManager methods
- virtual void NotifyAccessibilityEvent(int type, BrowserAccessibility* node)
- OVERRIDE;
+ virtual void NotifyAccessibilityEvent(
+ WebKit::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 d94c2c73df8..70ca4192a38 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h
@@ -23,8 +23,8 @@ class CONTENT_EXPORT BrowserAccessibilityManagerMac
static AccessibilityNodeData GetEmptyDocument();
// Implementation of BrowserAccessibilityManager.
- virtual void NotifyAccessibilityEvent(int type,
- BrowserAccessibility* node) OVERRIDE;
+ virtual void NotifyAccessibilityEvent(
+ WebKit::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 e3280997a25..1abf5fc5611 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
@@ -31,87 +31,108 @@ BrowserAccessibilityManagerMac::BrowserAccessibilityManagerMac(
AccessibilityNodeData BrowserAccessibilityManagerMac::GetEmptyDocument() {
AccessibilityNodeData empty_document;
empty_document.id = 0;
- empty_document.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA;
+ empty_document.role = WebKit::WebAXRoleRootWebArea;
empty_document.state =
- 1 << AccessibilityNodeData::STATE_READONLY;
+ 1 << WebKit::WebAXStateReadonly;
return empty_document;
}
void BrowserAccessibilityManagerMac::NotifyAccessibilityEvent(
- int type,
+ WebKit::WebAXEvent event_type,
BrowserAccessibility* node) {
if (!node->IsNative())
return;
// Refer to AXObjectCache.mm (webkit).
NSString* event_id = @"";
- switch (type) {
- case AccessibilityNotificationActiveDescendantChanged:
- if (node->role() == AccessibilityNodeData::ROLE_TREE)
+ switch (event_type) {
+ case WebKit::WebAXEventActiveDescendantChanged:
+ if (node->role() == WebKit::WebAXRoleTree)
event_id = NSAccessibilitySelectedRowsChangedNotification;
else
event_id = NSAccessibilityFocusedUIElementChangedNotification;
break;
- case AccessibilityNotificationAlert:
+ case WebKit::WebAXEventAlert:
// Not used on Mac.
return;
- case AccessibilityNotificationBlur:
+ case WebKit::WebAXEventBlur:
// A no-op on Mac.
return;
- case AccessibilityNotificationCheckStateChanged:
+ case WebKit::WebAXEventCheckedStateChanged:
// Not used on Mac.
return;
- case AccessibilityNotificationChildrenChanged:
+ case WebKit::WebAXEventChildrenChanged:
// TODO(dtseng): no clear equivalent on Mac.
return;
- case AccessibilityNotificationFocusChanged:
+ case WebKit::WebAXEventFocus:
event_id = NSAccessibilityFocusedUIElementChangedNotification;
break;
- case AccessibilityNotificationLayoutComplete:
+ case WebKit::WebAXEventLayoutComplete:
event_id = @"AXLayoutComplete";
break;
- case AccessibilityNotificationLiveRegionChanged:
+ case WebKit::WebAXEventLiveRegionChanged:
event_id = @"AXLiveRegionChanged";
break;
- case AccessibilityNotificationLoadComplete:
+ case WebKit::WebAXEventLoadComplete:
event_id = @"AXLoadComplete";
break;
- case AccessibilityNotificationMenuListValueChanged:
+ case WebKit::WebAXEventMenuListValueChanged:
// Not used on Mac.
return;
- case AccessibilityNotificationObjectShow:
+ case WebKit::WebAXEventShow:
// Not used on Mac.
return;
- case AccessibilityNotificationObjectHide:
+ case WebKit::WebAXEventHide:
// Not used on Mac.
return;
- case AccessibilityNotificationRowCountChanged:
+ case WebKit::WebAXEventRowCountChanged:
event_id = NSAccessibilityRowCountChangedNotification;
break;
- case AccessibilityNotificationRowCollapsed:
+ case WebKit::WebAXEventRowCollapsed:
event_id = @"AXRowCollapsed";
break;
- case AccessibilityNotificationRowExpanded:
+ case WebKit::WebAXEventRowExpanded:
event_id = @"AXRowExpanded";
break;
- case AccessibilityNotificationScrolledToAnchor:
+ case WebKit::WebAXEventScrolledToAnchor:
// Not used on Mac.
return;
- case AccessibilityNotificationSelectedChildrenChanged:
+ case WebKit::WebAXEventSelectedChildrenChanged:
event_id = NSAccessibilitySelectedChildrenChangedNotification;
break;
- case AccessibilityNotificationSelectedTextChanged:
+ case WebKit::WebAXEventSelectedTextChanged:
event_id = NSAccessibilitySelectedTextChangedNotification;
break;
- case AccessibilityNotificationTextInserted:
+ case WebKit::WebAXEventTextInserted:
// Not used on Mac.
return;
- case AccessibilityNotificationTextRemoved:
+ case WebKit::WebAXEventTextRemoved:
// Not used on Mac.
return;
- case AccessibilityNotificationValueChanged:
+ case WebKit::WebAXEventValueChanged:
event_id = NSAccessibilityValueChangedNotification;
break;
+ case WebKit::WebAXEventAriaAttributeChanged:
+ // Not used on Mac.
+ return;
+ case WebKit::WebAXEventAutocorrectionOccured:
+ // Not used on Mac.
+ return;
+ case WebKit::WebAXEventInvalidStatusChanged:
+ // Not used on Mac.
+ return;
+ case WebKit::WebAXEventLocationChanged:
+ // Not used on Mac.
+ return;
+ case WebKit::WebAXEventMenuListItemSelected:
+ // Not used on Mac.
+ return;
+ case WebKit::WebAXEventTextChanged:
+ // Not used on Mac.
+ return;
+ default:
+ LOG(WARNING) << "Unknown accessibility event: " << event_type;
+ return;
}
BrowserAccessibilityCocoa* native_node = node->ToBrowserAccessibilityCocoa();
DCHECK(native_node);
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc
index 5cb03cd25ce..d6a9f554c8f 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc
@@ -92,20 +92,20 @@ TEST(BrowserAccessibilityManagerTest, TestNoLeaks) {
// BrowserAccessibilityManager.
AccessibilityNodeData button;
button.id = 2;
- button.name = UTF8ToUTF16("Button");
- button.role = AccessibilityNodeData::ROLE_BUTTON;
+ button.SetName("Button");
+ button.role = WebKit::WebAXRoleButton;
button.state = 0;
AccessibilityNodeData checkbox;
checkbox.id = 3;
- checkbox.name = UTF8ToUTF16("Checkbox");
- checkbox.role = AccessibilityNodeData::ROLE_CHECKBOX;
+ checkbox.SetName("Checkbox");
+ checkbox.role = WebKit::WebAXRoleCheckBox;
checkbox.state = 0;
AccessibilityNodeData root;
root.id = 1;
- root.name = UTF8ToUTF16("Document");
- root.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA;
+ root.SetName("Document");
+ root.role = WebKit::WebAXRoleRootWebArea;
root.state = 0;
root.child_ids.push_back(2);
root.child_ids.push_back(3);
@@ -170,26 +170,26 @@ TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects) {
AccessibilityNodeData tree1_child1;
tree1_child1.id = 2;
- tree1_child1.name = UTF8ToUTF16("Child1");
- tree1_child1.role = AccessibilityNodeData::ROLE_BUTTON;
+ tree1_child1.SetName("Child1");
+ tree1_child1.role = WebKit::WebAXRoleButton;
tree1_child1.state = 0;
AccessibilityNodeData tree1_child2;
tree1_child2.id = 3;
- tree1_child2.name = UTF8ToUTF16("Child2");
- tree1_child2.role = AccessibilityNodeData::ROLE_BUTTON;
+ tree1_child2.SetName("Child2");
+ tree1_child2.role = WebKit::WebAXRoleButton;
tree1_child2.state = 0;
AccessibilityNodeData tree1_child3;
tree1_child3.id = 4;
- tree1_child3.name = UTF8ToUTF16("Child3");
- tree1_child3.role = AccessibilityNodeData::ROLE_BUTTON;
+ tree1_child3.SetName("Child3");
+ tree1_child3.role = WebKit::WebAXRoleButton;
tree1_child3.state = 0;
AccessibilityNodeData tree1_root;
tree1_root.id = 1;
- tree1_root.name = UTF8ToUTF16("Document");
- tree1_root.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA;
+ tree1_root.SetName("Document");
+ tree1_root.role = WebKit::WebAXRoleRootWebArea;
tree1_root.state = 0;
tree1_root.child_ids.push_back(2);
tree1_root.child_ids.push_back(3);
@@ -205,14 +205,14 @@ TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects) {
AccessibilityNodeData tree2_child0;
tree2_child0.id = 5;
- tree2_child0.name = UTF8ToUTF16("Child0");
- tree2_child0.role = AccessibilityNodeData::ROLE_BUTTON;
+ tree2_child0.SetName("Child0");
+ tree2_child0.role = WebKit::WebAXRoleButton;
tree2_child0.state = 0;
AccessibilityNodeData tree2_root;
tree2_root.id = 1;
- tree2_root.name = UTF8ToUTF16("DocumentChanged");
- tree2_root.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA;
+ tree2_root.SetName("DocumentChanged");
+ tree2_root.role = WebKit::WebAXRoleRootWebArea;
tree2_root.state = 0;
tree2_root.child_ids.push_back(5);
tree2_root.child_ids.push_back(2);
@@ -248,14 +248,14 @@ TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects) {
EXPECT_EQ(2, child3_accessible->index_in_parent());
// Process a notification containing the changed subtree.
- std::vector<AccessibilityHostMsg_NotificationParams> params;
- params.push_back(AccessibilityHostMsg_NotificationParams());
- AccessibilityHostMsg_NotificationParams* msg = &params[0];
- msg->notification_type = AccessibilityNotificationChildrenChanged;
+ std::vector<AccessibilityHostMsg_EventParams> params;
+ params.push_back(AccessibilityHostMsg_EventParams());
+ AccessibilityHostMsg_EventParams* msg = &params[0];
+ msg->event_type = WebKit::WebAXEventChildrenChanged;
msg->nodes.push_back(tree2_root);
msg->nodes.push_back(tree2_child0);
msg->id = tree2_root.id;
- manager->OnAccessibilityNotifications(params);
+ manager->OnAccessibilityEvents(params);
// There should be 5 objects now: the 4 from the new tree, plus the
// reference to child3 we kept.
@@ -302,47 +302,47 @@ TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects2) {
AccessibilityNodeData tree1_grandchild1;
tree1_grandchild1.id = 4;
- tree1_grandchild1.name = UTF8ToUTF16("GrandChild1");
- tree1_grandchild1.role = AccessibilityNodeData::ROLE_BUTTON;
+ tree1_grandchild1.SetName("GrandChild1");
+ tree1_grandchild1.role = WebKit::WebAXRoleButton;
tree1_grandchild1.state = 0;
AccessibilityNodeData tree1_child1;
tree1_child1.id = 3;
- tree1_child1.name = UTF8ToUTF16("Child1");
- tree1_child1.role = AccessibilityNodeData::ROLE_BUTTON;
+ tree1_child1.SetName("Child1");
+ tree1_child1.role = WebKit::WebAXRoleButton;
tree1_child1.state = 0;
tree1_child1.child_ids.push_back(4);
AccessibilityNodeData tree1_grandchild2;
tree1_grandchild2.id = 6;
- tree1_grandchild2.name = UTF8ToUTF16("GrandChild1");
- tree1_grandchild2.role = AccessibilityNodeData::ROLE_BUTTON;
+ tree1_grandchild2.SetName("GrandChild1");
+ tree1_grandchild2.role = WebKit::WebAXRoleButton;
tree1_grandchild2.state = 0;
AccessibilityNodeData tree1_child2;
tree1_child2.id = 5;
- tree1_child2.name = UTF8ToUTF16("Child2");
- tree1_child2.role = AccessibilityNodeData::ROLE_BUTTON;
+ tree1_child2.SetName("Child2");
+ tree1_child2.role = WebKit::WebAXRoleButton;
tree1_child2.state = 0;
tree1_child2.child_ids.push_back(6);
AccessibilityNodeData tree1_grandchild3;
tree1_grandchild3.id = 8;
- tree1_grandchild3.name = UTF8ToUTF16("GrandChild3");
- tree1_grandchild3.role = AccessibilityNodeData::ROLE_BUTTON;
+ tree1_grandchild3.SetName("GrandChild3");
+ tree1_grandchild3.role = WebKit::WebAXRoleButton;
tree1_grandchild3.state = 0;
AccessibilityNodeData tree1_child3;
tree1_child3.id = 7;
- tree1_child3.name = UTF8ToUTF16("Child3");
- tree1_child3.role = AccessibilityNodeData::ROLE_BUTTON;
+ tree1_child3.SetName("Child3");
+ tree1_child3.role = WebKit::WebAXRoleButton;
tree1_child3.state = 0;
tree1_child3.child_ids.push_back(8);
AccessibilityNodeData tree1_container;
tree1_container.id = 2;
- tree1_container.name = UTF8ToUTF16("Container");
- tree1_container.role = AccessibilityNodeData::ROLE_GROUP;
+ tree1_container.SetName("Container");
+ tree1_container.role = WebKit::WebAXRoleGroup;
tree1_container.state = 0;
tree1_container.child_ids.push_back(3);
tree1_container.child_ids.push_back(5);
@@ -350,8 +350,8 @@ TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects2) {
AccessibilityNodeData tree1_root;
tree1_root.id = 1;
- tree1_root.name = UTF8ToUTF16("Document");
- tree1_root.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA;
+ tree1_root.SetName("Document");
+ tree1_root.role = WebKit::WebAXRoleRootWebArea;
tree1_root.state = 0;
tree1_root.child_ids.push_back(2);
@@ -369,21 +369,21 @@ TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects2) {
AccessibilityNodeData tree2_grandchild0;
tree2_grandchild0.id = 9;
- tree2_grandchild0.name = UTF8ToUTF16("GrandChild0");
- tree2_grandchild0.role = AccessibilityNodeData::ROLE_BUTTON;
+ tree2_grandchild0.SetName("GrandChild0");
+ tree2_grandchild0.role = WebKit::WebAXRoleButton;
tree2_grandchild0.state = 0;
AccessibilityNodeData tree2_child0;
tree2_child0.id = 10;
- tree2_child0.name = UTF8ToUTF16("Child0");
- tree2_child0.role = AccessibilityNodeData::ROLE_BUTTON;
+ tree2_child0.SetName("Child0");
+ tree2_child0.role = WebKit::WebAXRoleButton;
tree2_child0.state = 0;
tree2_child0.child_ids.push_back(9);
AccessibilityNodeData tree2_container;
tree2_container.id = 2;
- tree2_container.name = UTF8ToUTF16("Container");
- tree2_container.role = AccessibilityNodeData::ROLE_GROUP;
+ tree2_container.SetName("Container");
+ tree2_container.role = WebKit::WebAXRoleGroup;
tree2_container.state = 0;
tree2_container.child_ids.push_back(10);
tree2_container.child_ids.push_back(3);
@@ -424,15 +424,15 @@ TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects2) {
// Process a notification containing the changed subtree rooted at
// the container.
- std::vector<AccessibilityHostMsg_NotificationParams> params;
- params.push_back(AccessibilityHostMsg_NotificationParams());
- AccessibilityHostMsg_NotificationParams* msg = &params[0];
- msg->notification_type = AccessibilityNotificationChildrenChanged;
+ std::vector<AccessibilityHostMsg_EventParams> params;
+ params.push_back(AccessibilityHostMsg_EventParams());
+ AccessibilityHostMsg_EventParams* msg = &params[0];
+ msg->event_type = WebKit::WebAXEventChildrenChanged;
msg->nodes.push_back(tree2_container);
msg->nodes.push_back(tree2_child0);
msg->nodes.push_back(tree2_grandchild0);
msg->id = tree2_container.id;
- manager->OnAccessibilityNotifications(params);
+ manager->OnAccessibilityEvents(params);
// There should be 9 objects now: the 8 from the new tree, plus the
// reference to child3 we kept.
@@ -489,7 +489,7 @@ TEST(BrowserAccessibilityManagerTest, TestMoveChildUp) {
AccessibilityNodeData tree1_1;
tree1_1.id = 1;
- tree1_1.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA;
+ tree1_1.role = WebKit::WebAXRoleRootWebArea;
tree1_1.state = 0;
tree1_1.child_ids.push_back(2);
tree1_1.child_ids.push_back(3);
@@ -531,16 +531,16 @@ TEST(BrowserAccessibilityManagerTest, TestMoveChildUp) {
ASSERT_EQ(4, CountedBrowserAccessibility::global_obj_count_);
// Process a notification containing the changed subtree.
- std::vector<AccessibilityHostMsg_NotificationParams> params;
- params.push_back(AccessibilityHostMsg_NotificationParams());
- AccessibilityHostMsg_NotificationParams* msg = &params[0];
- msg->notification_type = AccessibilityNotificationChildrenChanged;
+ std::vector<AccessibilityHostMsg_EventParams> params;
+ params.push_back(AccessibilityHostMsg_EventParams());
+ AccessibilityHostMsg_EventParams* msg = &params[0];
+ msg->event_type = WebKit::WebAXEventChildrenChanged;
msg->nodes.push_back(tree2_1);
msg->nodes.push_back(tree2_4);
msg->nodes.push_back(tree2_5);
msg->nodes.push_back(tree2_6);
msg->id = tree2_1.id;
- manager->OnAccessibilityNotifications(params);
+ manager->OnAccessibilityEvents(params);
// There should be 4 objects now.
EXPECT_EQ(4, CountedBrowserAccessibility::global_obj_count_);
@@ -557,7 +557,7 @@ TEST(BrowserAccessibilityManagerTest, TestFatalError) {
AccessibilityNodeData root;
root.id = 1;
- root.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA;
+ root.role = WebKit::WebAXRoleRootWebArea;
root.child_ids.push_back(2);
root.child_ids.push_back(2);
@@ -575,7 +575,7 @@ TEST(BrowserAccessibilityManagerTest, TestFatalError) {
AccessibilityNodeData root2;
root2.id = 1;
- root2.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA;
+ root2.role = WebKit::WebAXRoleRootWebArea;
root2.child_ids.push_back(2);
root2.child_ids.push_back(3);
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
index b956d218d33..881d1b80b25 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
@@ -46,10 +46,11 @@ BrowserAccessibilityManagerWin::~BrowserAccessibilityManagerWin() {
AccessibilityNodeData BrowserAccessibilityManagerWin::GetEmptyDocument() {
AccessibilityNodeData empty_document;
empty_document.id = 0;
- empty_document.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA;
+ empty_document.role = WebKit::WebAXRoleRootWebArea;
empty_document.state =
- (1 << AccessibilityNodeData::STATE_READONLY) |
- (1 << AccessibilityNodeData::STATE_BUSY);
+ (1 << WebKit::WebAXStateEnabled) |
+ (1 << WebKit::WebAXStateReadonly) |
+ (1 << WebKit::WebAXStateBusy);
return empty_document;
}
@@ -76,79 +77,79 @@ void BrowserAccessibilityManagerWin::RemoveNode(BrowserAccessibility* node) {
}
void BrowserAccessibilityManagerWin::NotifyAccessibilityEvent(
- int type,
+ WebKit::WebAXEvent event_type,
BrowserAccessibility* node) {
LONG event_id = EVENT_MIN;
- switch (type) {
- case AccessibilityNotificationActiveDescendantChanged:
+ switch (event_type) {
+ case WebKit::WebAXEventActiveDescendantChanged:
event_id = IA2_EVENT_ACTIVE_DESCENDANT_CHANGED;
break;
- case AccessibilityNotificationAlert:
+ case WebKit::WebAXEventAlert:
event_id = EVENT_SYSTEM_ALERT;
break;
- case AccessibilityNotificationAriaAttributeChanged:
+ case WebKit::WebAXEventAriaAttributeChanged:
event_id = IA2_EVENT_OBJECT_ATTRIBUTE_CHANGED;
break;
- case AccessibilityNotificationAutocorrectionOccurred:
+ case WebKit::WebAXEventAutocorrectionOccured:
event_id = IA2_EVENT_OBJECT_ATTRIBUTE_CHANGED;
break;
- case AccessibilityNotificationBlur:
+ case WebKit::WebAXEventBlur:
// Equivalent to focus on the root.
event_id = EVENT_OBJECT_FOCUS;
node = GetRoot();
break;
- case AccessibilityNotificationCheckStateChanged:
+ case WebKit::WebAXEventCheckedStateChanged:
event_id = EVENT_OBJECT_STATECHANGE;
break;
- case AccessibilityNotificationChildrenChanged:
+ case WebKit::WebAXEventChildrenChanged:
event_id = EVENT_OBJECT_REORDER;
break;
- case AccessibilityNotificationFocusChanged:
+ case WebKit::WebAXEventFocus:
event_id = EVENT_OBJECT_FOCUS;
break;
- case AccessibilityNotificationInvalidStatusChanged:
+ case WebKit::WebAXEventInvalidStatusChanged:
event_id = EVENT_OBJECT_STATECHANGE;
break;
- case AccessibilityNotificationLiveRegionChanged:
+ case WebKit::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 AccessibilityNotificationLoadComplete:
+ case WebKit::WebAXEventLoadComplete:
event_id = IA2_EVENT_DOCUMENT_LOAD_COMPLETE;
break;
- case AccessibilityNotificationMenuListItemSelected:
+ case WebKit::WebAXEventMenuListItemSelected:
event_id = EVENT_OBJECT_FOCUS;
break;
- case AccessibilityNotificationMenuListValueChanged:
+ case WebKit::WebAXEventMenuListValueChanged:
event_id = EVENT_OBJECT_VALUECHANGE;
break;
- case AccessibilityNotificationObjectHide:
+ case WebKit::WebAXEventHide:
event_id = EVENT_OBJECT_HIDE;
break;
- case AccessibilityNotificationObjectShow:
+ case WebKit::WebAXEventShow:
event_id = EVENT_OBJECT_SHOW;
break;
- case AccessibilityNotificationScrolledToAnchor:
+ case WebKit::WebAXEventScrolledToAnchor:
event_id = EVENT_SYSTEM_SCROLLINGSTART;
break;
- case AccessibilityNotificationSelectedChildrenChanged:
+ case WebKit::WebAXEventSelectedChildrenChanged:
event_id = EVENT_OBJECT_SELECTIONWITHIN;
break;
- case AccessibilityNotificationSelectedTextChanged:
+ case WebKit::WebAXEventSelectedTextChanged:
event_id = IA2_EVENT_TEXT_CARET_MOVED;
break;
- case AccessibilityNotificationTextChanged:
+ case WebKit::WebAXEventTextChanged:
event_id = EVENT_OBJECT_NAMECHANGE;
break;
- case AccessibilityNotificationTextInserted:
+ case WebKit::WebAXEventTextInserted:
event_id = IA2_EVENT_TEXT_INSERTED;
break;
- case AccessibilityNotificationTextRemoved:
+ case WebKit::WebAXEventTextRemoved:
event_id = IA2_EVENT_TEXT_REMOVED;
break;
- case AccessibilityNotificationValueChanged:
+ case WebKit::WebAXEventValueChanged:
event_id = EVENT_OBJECT_VALUECHANGE;
break;
default:
@@ -169,7 +170,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 (type == AccessibilityNotificationLayoutComplete &&
+ if (event_type == WebKit::WebAXEventLayoutComplete &&
tracked_scroll_object_ &&
tracked_scroll_object_->IsDescendantOf(node)) {
MaybeCallNotifyWinEvent(
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_win.h b/chromium/content/browser/accessibility/browser_accessibility_manager_win.h
index 7aec2e1c5e9..7857f68a76e 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_win.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_win.h
@@ -43,8 +43,8 @@ class CONTENT_EXPORT BrowserAccessibilityManagerWin
// BrowserAccessibilityManager methods
virtual void AddNodeToMap(BrowserAccessibility* node);
virtual void RemoveNode(BrowserAccessibility* node) OVERRIDE;
- virtual void NotifyAccessibilityEvent(int type, BrowserAccessibility* node)
- OVERRIDE;
+ virtual void NotifyAccessibilityEvent(
+ WebKit::WebAXEvent event_type, BrowserAccessibility* node) OVERRIDE;
// Track this object and post a VISIBLE_DATA_CHANGED notification when
// its container scrolls.
diff --git a/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc b/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc
index befd717bc0c..3dee7d62b33 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc
@@ -10,6 +10,7 @@
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_widget_host_iterator.h"
#include "content/public/common/content_switches.h"
#include "ui/gfx/sys_color_change_listener.h"
@@ -131,16 +132,16 @@ void BrowserAccessibilityStateImpl::SetAccessibilityMode(
// Iterate over all RenderWidgetHosts, even swapped out ones in case
// they become active again.
- RenderWidgetHost::List widgets =
- RenderWidgetHostImpl::GetAllRenderWidgetHosts();
- for (size_t i = 0; i < widgets.size(); ++i) {
+ scoped_ptr<RenderWidgetHostIterator> widgets(
+ RenderWidgetHostImpl::GetAllRenderWidgetHosts());
+ while (RenderWidgetHost* widget = widgets->GetNextHost()) {
// Ignore processes that don't have a connection, such as crashed tabs.
- if (!widgets[i]->GetProcess()->HasConnection())
+ if (!widget->GetProcess()->HasConnection())
continue;
- if (!widgets[i]->IsRenderView())
+ if (!widget->IsRenderView())
continue;
- RenderWidgetHostImpl::From(widgets[i])->SetAccessibilityMode(mode);
+ RenderWidgetHostImpl::From(widget)->SetAccessibilityMode(mode);
}
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_win.cc b/chromium/content/browser/accessibility/browser_accessibility_win.cc
index 792adc4440d..df3263e845d 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_win.cc
@@ -15,6 +15,7 @@
#include "base/win/scoped_comptr.h"
#include "base/win/windows_version.h"
#include "content/browser/accessibility/browser_accessibility_manager_win.h"
+#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/common/accessibility_messages.h"
#include "content/public/common/content_client.h"
#include "ui/base/accessibility/accessible_text_utils.h"
@@ -457,7 +458,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accName(VARIANT var_id, BSTR* name) {
if (!target)
return E_INVALIDARG;
- string16 name_str = target->name_;
+ std::string name_str = target->name();
// If the name is empty, see if it's labeled by another element.
if (name_str.empty()) {
@@ -474,7 +475,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accName(VARIANT var_id, BSTR* name) {
if (name_str.empty())
return S_FALSE;
- *name = SysAllocString(name_str.c_str());
+ *name = SysAllocString(UTF8ToUTF16(name_str).c_str());
DCHECK(*name);
return S_OK;
@@ -557,8 +558,33 @@ STDMETHODIMP BrowserAccessibilityWin::get_accValue(VARIANT var_id,
if (!target)
return E_INVALIDARG;
- *value = SysAllocString(target->value_.c_str());
+ if (target->ia_role() == ROLE_SYSTEM_PROGRESSBAR ||
+ target->ia_role() == ROLE_SYSTEM_SCROLLBAR ||
+ target->ia_role() == ROLE_SYSTEM_SLIDER) {
+ string16 value_text = target->GetValueText();
+ *value = SysAllocString(value_text.c_str());
+ DCHECK(*value);
+ return S_OK;
+ }
+
+ // Expose color well value.
+ if (target->ia2_role() == IA2_ROLE_COLOR_CHOOSER) {
+ int r = target->GetIntAttribute(
+ AccessibilityNodeData::ATTR_COLOR_VALUE_RED);
+ int g = target->GetIntAttribute(
+ AccessibilityNodeData::ATTR_COLOR_VALUE_GREEN);
+ int b = target->GetIntAttribute(
+ AccessibilityNodeData::ATTR_COLOR_VALUE_BLUE);
+ 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";
+ *value = SysAllocString(value_text.c_str());
+ DCHECK(*value);
+ return S_OK;
+ }
+ *value = SysAllocString(UTF8ToUTF16(target->value()).c_str());
DCHECK(*value);
return S_OK;
}
@@ -573,12 +599,12 @@ STDMETHODIMP BrowserAccessibilityWin::get_accSelection(VARIANT* selected) {
if (!instance_active_)
return E_FAIL;
- if (role_ != AccessibilityNodeData::ROLE_LISTBOX)
+ if (role_ != WebKit::WebAXRoleListBox)
return E_NOTIMPL;
unsigned long selected_count = 0;
for (size_t i = 0; i < children_.size(); ++i) {
- if (children_[i]->HasState(AccessibilityNodeData::STATE_SELECTED))
+ if (children_[i]->HasState(WebKit::WebAXStateSelected))
++selected_count;
}
@@ -589,7 +615,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accSelection(VARIANT* selected) {
if (selected_count == 1) {
for (size_t i = 0; i < children_.size(); ++i) {
- if (children_[i]->HasState(AccessibilityNodeData::STATE_SELECTED)) {
+ if (children_[i]->HasState(WebKit::WebAXStateSelected)) {
selected->vt = VT_DISPATCH;
selected->pdispVal =
children_[i]->ToBrowserAccessibilityWin()->NewReference();
@@ -604,7 +630,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accSelection(VARIANT* selected) {
enum_variant->AddRef();
unsigned long index = 0;
for (size_t i = 0; i < children_.size(); ++i) {
- if (children_[i]->HasState(AccessibilityNodeData::STATE_SELECTED)) {
+ if (children_[i]->HasState(WebKit::WebAXStateSelected)) {
enum_variant->ItemAt(index)->vt = VT_DISPATCH;
enum_variant->ItemAt(index)->pdispVal =
children_[i]->ToBrowserAccessibilityWin()->NewReference();
@@ -845,9 +871,9 @@ STDMETHODIMP BrowserAccessibilityWin::get_groupPosition(
if (!group_level || !similar_items_in_group || !position_in_group)
return E_INVALIDARG;
- if (role_ == AccessibilityNodeData::ROLE_LISTBOX_OPTION &&
+ if (role_ == WebKit::WebAXRoleListBoxOption &&
parent_ &&
- parent_->role() == AccessibilityNodeData::ROLE_LISTBOX) {
+ parent_->role() == WebKit::WebAXRoleListBox) {
*group_level = 0;
*similar_items_in_group = parent_->child_count();
*position_in_group = index_in_parent_ + 1;
@@ -1014,9 +1040,11 @@ STDMETHODIMP BrowserAccessibilityWin::get_accessibleAt(
if (row < 0 || row >= rows || column < 0 || column >= columns)
return E_INVALIDARG;
- DCHECK_EQ(columns * rows, static_cast<int>(cell_ids_.size()));
+ const std::vector<int32>& cell_ids = GetIntListAttribute(
+ AccessibilityNodeData::ATTR_CELL_IDS);
+ DCHECK_EQ(columns * rows, static_cast<int>(cell_ids.size()));
- int cell_id = cell_ids_[row * columns + column];
+ int cell_id = cell_ids[row * columns + column];
BrowserAccessibilityWin* cell = GetFromRendererID(cell_id);
if (cell) {
*accessible = static_cast<IAccessible*>(cell->NewReference());
@@ -1061,10 +1089,14 @@ STDMETHODIMP BrowserAccessibilityWin::get_childIndex(long row,
if (row < 0 || row >= rows || column < 0 || column >= columns)
return E_INVALIDARG;
- DCHECK_EQ(columns * rows, static_cast<int>(cell_ids_.size()));
- int cell_id = cell_ids_[row * columns + column];
- for (size_t i = 0; i < unique_cell_ids_.size(); ++i) {
- if (unique_cell_ids_[i] == cell_id) {
+ const std::vector<int32>& cell_ids = GetIntListAttribute(
+ AccessibilityNodeData::ATTR_CELL_IDS);
+ const std::vector<int32>& unique_cell_ids = GetIntListAttribute(
+ AccessibilityNodeData::ATTR_UNIQUE_CELL_IDS);
+ DCHECK_EQ(columns * rows, static_cast<int>(cell_ids.size()));
+ int cell_id = cell_ids[row * columns + column];
+ for (size_t i = 0; i < unique_cell_ids.size(); ++i) {
+ if (unique_cell_ids[i] == cell_id) {
*cell_index = (long)i;
return S_OK;
}
@@ -1094,13 +1126,17 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnDescription(long column,
if (column < 0 || column >= columns)
return E_INVALIDARG;
+ const std::vector<int32>& cell_ids = GetIntListAttribute(
+ AccessibilityNodeData::ATTR_CELL_IDS);
for (int i = 0; i < rows; ++i) {
- int cell_id = cell_ids_[i * columns + column];
+ int cell_id = cell_ids[i * columns + column];
BrowserAccessibilityWin* cell = static_cast<BrowserAccessibilityWin*>(
manager_->GetFromRendererID(cell_id));
- if (cell && cell->role_ == AccessibilityNodeData::ROLE_COLUMN_HEADER) {
- if (cell->name_.size() > 0) {
- *description = SysAllocString(cell->name_.c_str());
+ if (cell && cell->role_ == WebKit::WebAXRoleColumnHeader) {
+ string16 cell_name = cell->GetString16Attribute(
+ AccessibilityNodeData::ATTR_NAME);
+ if (cell_name.size() > 0) {
+ *description = SysAllocString(cell_name.c_str());
return S_OK;
}
@@ -1135,7 +1171,9 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnExtentAt(
if (row < 0 || row >= rows || column < 0 || column >= columns)
return E_INVALIDARG;
- int cell_id = cell_ids_[row * columns + column];
+ const std::vector<int32>& cell_ids = GetIntListAttribute(
+ AccessibilityNodeData::ATTR_CELL_IDS);
+ int cell_id = cell_ids[row * columns + column];
BrowserAccessibilityWin* cell = static_cast<BrowserAccessibilityWin*>(
manager_->GetFromRendererID(cell_id));
int colspan;
@@ -1165,13 +1203,15 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnIndex(long cell_index,
if (!column_index)
return E_INVALIDARG;
- int cell_id_count = static_cast<int>(unique_cell_ids_.size());
+ const std::vector<int32>& unique_cell_ids = GetIntListAttribute(
+ AccessibilityNodeData::ATTR_UNIQUE_CELL_IDS);
+ int cell_id_count = static_cast<int>(unique_cell_ids.size());
if (cell_index < 0)
return E_INVALIDARG;
if (cell_index >= cell_id_count)
return S_FALSE;
- int cell_id = unique_cell_ids_[cell_index];
+ int cell_id = unique_cell_ids[cell_index];
BrowserAccessibilityWin* cell =
manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin();
int col_index;
@@ -1273,13 +1313,17 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowDescription(long row,
if (row < 0 || row >= rows)
return E_INVALIDARG;
+ const std::vector<int32>& cell_ids = GetIntListAttribute(
+ AccessibilityNodeData::ATTR_CELL_IDS);
for (int i = 0; i < columns; ++i) {
- int cell_id = cell_ids_[row * columns + i];
+ int cell_id = cell_ids[row * columns + i];
BrowserAccessibilityWin* cell =
manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin();
- if (cell && cell->role_ == AccessibilityNodeData::ROLE_ROW_HEADER) {
- if (cell->name_.size() > 0) {
- *description = SysAllocString(cell->name_.c_str());
+ if (cell && cell->role_ == WebKit::WebAXRoleRowHeader) {
+ string16 cell_name = cell->GetString16Attribute(
+ AccessibilityNodeData::ATTR_NAME);
+ if (cell_name.size() > 0) {
+ *description = SysAllocString(cell_name.c_str());
return S_OK;
}
@@ -1313,7 +1357,9 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowExtentAt(long row,
if (row < 0 || row >= rows || column < 0 || column >= columns)
return E_INVALIDARG;
- int cell_id = cell_ids_[row * columns + column];
+ const std::vector<int32>& cell_ids = GetIntListAttribute(
+ AccessibilityNodeData::ATTR_CELL_IDS);
+ int cell_id = cell_ids[row * columns + column];
BrowserAccessibilityWin* cell =
manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin();
int rowspan;
@@ -1343,13 +1389,15 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowIndex(long cell_index,
if (!row_index)
return E_INVALIDARG;
- int cell_id_count = static_cast<int>(unique_cell_ids_.size());
+ const std::vector<int32>& unique_cell_ids = GetIntListAttribute(
+ AccessibilityNodeData::ATTR_UNIQUE_CELL_IDS);
+ int cell_id_count = static_cast<int>(unique_cell_ids.size());
if (cell_index < 0)
return E_INVALIDARG;
if (cell_index >= cell_id_count)
return S_FALSE;
- int cell_id = unique_cell_ids_[cell_index];
+ int cell_id = unique_cell_ids[cell_index];
BrowserAccessibilityWin* cell =
manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin();
int cell_row_index;
@@ -1470,13 +1518,15 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowColumnExtentsAtIndex(
if (!row || !column || !row_extents || !column_extents || !is_selected)
return E_INVALIDARG;
- int cell_id_count = static_cast<int>(unique_cell_ids_.size());
+ const std::vector<int32>& unique_cell_ids = GetIntListAttribute(
+ AccessibilityNodeData::ATTR_UNIQUE_CELL_IDS);
+ int cell_id_count = static_cast<int>(unique_cell_ids.size());
if (index < 0)
return E_INVALIDARG;
if (index >= cell_id_count)
return S_FALSE;
- int cell_id = unique_cell_ids_[index];
+ int cell_id = unique_cell_ids[index];
BrowserAccessibilityWin* cell =
manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin();
int rowspan;
@@ -1592,7 +1642,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnHeaderCells(
}
BrowserAccessibility* table = parent();
- while (table && table->role() != AccessibilityNodeData::ROLE_TABLE)
+ while (table && table->role() != WebKit::WebAXRoleTable)
table = table->parent();
if (!table) {
NOTREACHED();
@@ -1610,11 +1660,14 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnHeaderCells(
if (columns <= 0 || rows <= 0 || column < 0 || column >= columns)
return S_FALSE;
+ const std::vector<int32>& cell_ids = table->GetIntListAttribute(
+ AccessibilityNodeData::ATTR_CELL_IDS);
+
for (int i = 0; i < rows; ++i) {
- int cell_id = table->cell_ids()[i * columns + column];
+ int cell_id = cell_ids[i * columns + column];
BrowserAccessibilityWin* cell =
manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin();
- if (cell && cell->role_ == AccessibilityNodeData::ROLE_COLUMN_HEADER)
+ if (cell && cell->role_ == WebKit::WebAXRoleColumnHeader)
(*n_column_header_cells)++;
}
@@ -1622,10 +1675,10 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnHeaderCells(
(*n_column_header_cells) * sizeof(cell_accessibles[0])));
int index = 0;
for (int i = 0; i < rows; ++i) {
- int cell_id = table->cell_ids()[i * columns + column];
+ int cell_id = cell_ids[i * columns + column];
BrowserAccessibilityWin* cell =
manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin();
- if (cell && cell->role_ == AccessibilityNodeData::ROLE_COLUMN_HEADER) {
+ if (cell && cell->role_ == WebKit::WebAXRoleColumnHeader) {
(*cell_accessibles)[index] =
static_cast<IAccessible*>(cell->NewReference());
++index;
@@ -1688,7 +1741,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowHeaderCells(
}
BrowserAccessibility* table = parent();
- while (table && table->role() != AccessibilityNodeData::ROLE_TABLE)
+ while (table && table->role() != WebKit::WebAXRoleTable)
table = table->parent();
if (!table) {
NOTREACHED();
@@ -1706,11 +1759,14 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowHeaderCells(
if (columns <= 0 || rows <= 0 || row < 0 || row >= rows)
return S_FALSE;
+ const std::vector<int32>& cell_ids = table->GetIntListAttribute(
+ AccessibilityNodeData::ATTR_CELL_IDS);
+
for (int i = 0; i < columns; ++i) {
- int cell_id = table->cell_ids()[row * columns + i];
+ int cell_id = cell_ids[row * columns + i];
BrowserAccessibilityWin* cell =
manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin();
- if (cell && cell->role_ == AccessibilityNodeData::ROLE_ROW_HEADER)
+ if (cell && cell->role_ == WebKit::WebAXRoleRowHeader)
(*n_row_header_cells)++;
}
@@ -1718,10 +1774,10 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowHeaderCells(
(*n_row_header_cells) * sizeof(cell_accessibles[0])));
int index = 0;
for (int i = 0; i < columns; ++i) {
- int cell_id = table->cell_ids()[row * columns + i];
+ int cell_id = cell_ids[row * columns + i];
BrowserAccessibilityWin* cell =
manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin();
- if (cell && cell->role_ == AccessibilityNodeData::ROLE_ROW_HEADER) {
+ if (cell && cell->role_ == WebKit::WebAXRoleRowHeader) {
(*cell_accessibles)[index] =
static_cast<IAccessible*>(cell->NewReference());
++index;
@@ -1810,7 +1866,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() != AccessibilityNodeData::ROLE_TABLE)
+ while (find_table && find_table->role() != WebKit::WebAXRoleTable)
find_table = find_table->parent();
if (!find_table) {
NOTREACHED();
@@ -1846,8 +1902,8 @@ STDMETHODIMP BrowserAccessibilityWin::get_caretOffset(LONG* offset) {
return E_INVALIDARG;
*offset = 0;
- if (role_ == AccessibilityNodeData::ROLE_TEXT_FIELD ||
- role_ == AccessibilityNodeData::ROLE_TEXTAREA) {
+ if (role_ == WebKit::WebAXRoleTextField ||
+ role_ == WebKit::WebAXRoleTextArea) {
int sel_start = 0;
if (GetIntAttribute(AccessibilityNodeData::ATTR_TEXT_SEL_START,
&sel_start))
@@ -1865,8 +1921,8 @@ STDMETHODIMP BrowserAccessibilityWin::get_nSelections(LONG* n_selections) {
return E_INVALIDARG;
*n_selections = 0;
- if (role_ == AccessibilityNodeData::ROLE_TEXT_FIELD ||
- role_ == AccessibilityNodeData::ROLE_TEXTAREA) {
+ if (role_ == WebKit::WebAXRoleTextField ||
+ role_ == WebKit::WebAXRoleTextArea) {
int sel_start = 0;
int sel_end = 0;
if (GetIntAttribute(AccessibilityNodeData::ATTR_TEXT_SEL_START,
@@ -1890,8 +1946,8 @@ STDMETHODIMP BrowserAccessibilityWin::get_selection(LONG selection_index,
*start_offset = 0;
*end_offset = 0;
- if (role_ == AccessibilityNodeData::ROLE_TEXT_FIELD ||
- role_ == AccessibilityNodeData::ROLE_TEXTAREA) {
+ if (role_ == WebKit::WebAXRoleTextField ||
+ role_ == WebKit::WebAXRoleTextArea) {
int sel_start = 0;
int sel_end = 0;
if (GetIntAttribute(
@@ -2334,13 +2390,13 @@ STDMETHODIMP BrowserAccessibilityWin::get_nodeInfo(
}
string16 tag;
- if (GetStringAttribute(AccessibilityNodeData::ATTR_HTML_TAG, &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(value_.c_str());
+ *node_value = SysAllocString(UTF8ToUTF16(value_).c_str());
*num_children = children_.size();
*unique_id = unique_id_win_;
@@ -2373,9 +2429,11 @@ STDMETHODIMP BrowserAccessibilityWin::get_attributes(
*num_attribs = html_attributes_.size();
for (unsigned short i = 0; i < *num_attribs; ++i) {
- attrib_names[i] = SysAllocString(html_attributes_[i].first.c_str());
+ attrib_names[i] = SysAllocString(
+ UTF8ToUTF16(html_attributes_[i].first).c_str());
name_space_id[i] = 0;
- attrib_values[i] = SysAllocString(html_attributes_[i].second.c_str());
+ attrib_values[i] = SysAllocString(
+ UTF8ToUTF16(html_attributes_[i].second).c_str());
}
return S_OK;
}
@@ -2394,10 +2452,11 @@ STDMETHODIMP BrowserAccessibilityWin::get_attributesForNames(
for (unsigned short i = 0; i < num_attribs; ++i) {
name_space_id[i] = 0;
bool found = false;
- string16 name = (LPCWSTR)attrib_names[i];
+ std::string name = UTF16ToUTF8((LPCWSTR)attrib_names[i]);
for (unsigned int j = 0; j < html_attributes_.size(); ++j) {
if (html_attributes_[j].first == name) {
- attrib_values[i] = SysAllocString(html_attributes_[j].second.c_str());
+ attrib_values[i] = SysAllocString(
+ UTF8ToUTF16(html_attributes_[j].second).c_str());
found = true;
break;
}
@@ -2425,7 +2484,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_computedStyle(
string16 display;
if (max_style_properties == 0 ||
- !GetStringAttribute(AccessibilityNodeData::ATTR_DISPLAY, &display)) {
+ !GetString16Attribute(AccessibilityNodeData::ATTR_DISPLAY, &display)) {
*num_style_properties = 0;
return S_OK;
}
@@ -2454,8 +2513,8 @@ STDMETHODIMP BrowserAccessibilityWin::get_computedStyleForProperties(
string16 name = (LPCWSTR)style_properties[i];
StringToLowerASCII(&name);
if (name == L"display") {
- string16 display;
- GetStringAttribute(AccessibilityNodeData::ATTR_DISPLAY, &display);
+ string16 display = GetString16Attribute(
+ AccessibilityNodeData::ATTR_DISPLAY);
style_values[i] = SysAllocString(display.c_str());
} else {
style_values[i] = NULL;
@@ -2579,12 +2638,8 @@ STDMETHODIMP BrowserAccessibilityWin::get_domText(BSTR* dom_text) {
if (!dom_text)
return E_INVALIDARG;
- if (name_.empty())
- return S_FALSE;
-
- *dom_text = SysAllocString(name_.c_str());
- DCHECK(*dom_text);
- return S_OK;
+ return GetStringAttributeAsBstr(
+ AccessibilityNodeData::ATTR_NAME, dom_text);
}
//
@@ -2597,6 +2652,12 @@ STDMETHODIMP BrowserAccessibilityWin::QueryService(REFGUID guidService,
if (!instance_active_)
return E_FAIL;
+ // The system uses IAccessible APIs for many purposes, but only
+ // assistive technology like screen readers uses IAccessible2.
+ // Enable full accessibility support when IAccessible2 APIs are queried.
+ if (riid == IID_IAccessible2)
+ BrowserAccessibilityStateImpl::GetInstance()->EnableAccessibility();
+
if (guidService == GUID_IAccessibleContentDocument) {
// Special Mozilla extension: return the accessible for the root document.
// Screen readers use this to distinguish between a document loaded event
@@ -2738,9 +2799,9 @@ void BrowserAccessibilityWin::PreInitialize() {
IntAttributeToIA2(AccessibilityNodeData::ATTR_HIERARCHICAL_LEVEL, "level");
// Expose the set size and position in set for listbox options.
- if (role_ == AccessibilityNodeData::ROLE_LISTBOX_OPTION &&
+ if (role_ == WebKit::WebAXRoleListBoxOption &&
parent_ &&
- parent_->role() == AccessibilityNodeData::ROLE_LISTBOX) {
+ parent_->role() == WebKit::WebAXRoleListBox) {
ia2_attributes_.push_back(
L"setsize:" + base::IntToString16(parent_->child_count()));
ia2_attributes_.push_back(
@@ -2773,33 +2834,17 @@ void BrowserAccessibilityWin::PreInitialize() {
if (ia_role_ == ROLE_SYSTEM_PROGRESSBAR ||
ia_role_ == ROLE_SYSTEM_SCROLLBAR ||
ia_role_ == ROLE_SYSTEM_SLIDER) {
- float fval;
- if (value_.empty() &&
- GetFloatAttribute(AccessibilityNodeData::ATTR_VALUE_FOR_RANGE, &fval)) {
- // TODO(dmazzoni): Use ICU to localize this?
- value_ = UTF8ToUTF16(base::DoubleToString(fval));
- }
- ia2_attributes_.push_back(L"valuetext:" + value_);
- }
-
- // Expose color well value.
- if (ia2_role_ == IA2_ROLE_COLOR_CHOOSER) {
- int r, g, b;
- GetIntAttribute(AccessibilityNodeData::ATTR_COLOR_VALUE_RED, &r);
- GetIntAttribute(AccessibilityNodeData::ATTR_COLOR_VALUE_GREEN, &g);
- GetIntAttribute(AccessibilityNodeData::ATTR_COLOR_VALUE_BLUE, &b);
- value_ = base::IntToString16((r * 100) / 255) + L"% red " +
- base::IntToString16((g * 100) / 255) + L"% green " +
- base::IntToString16((b * 100) / 255) + L"% blue";
+ ia2_attributes_.push_back(L"valuetext:" + GetValueText());
}
// Expose table cell index.
if (ia_role_ == ROLE_SYSTEM_CELL) {
BrowserAccessibility* table = parent();
- while (table && table->role() != AccessibilityNodeData::ROLE_TABLE)
+ while (table && table->role() != WebKit::WebAXRoleTable)
table = table->parent();
if (table) {
- const std::vector<int32>& unique_cell_ids = table->unique_cell_ids();
+ 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_) {
ia2_attributes_.push_back(
@@ -2830,22 +2875,21 @@ void BrowserAccessibilityWin::PreInitialize() {
// always returns the primary name in "name" and the secondary name,
// if any, in "description".
- string16 description, help, title_attr;
- int title_elem_id = 0;
- GetIntAttribute(AccessibilityNodeData::ATTR_TITLE_UI_ELEMENT, &title_elem_id);
- GetStringAttribute(AccessibilityNodeData::ATTR_DESCRIPTION, &description);
- GetStringAttribute(AccessibilityNodeData::ATTR_HELP, &help);
+ int title_elem_id = GetIntAttribute(
+ AccessibilityNodeData::ATTR_TITLE_UI_ELEMENT);
+ std::string help = GetStringAttribute(AccessibilityNodeData::ATTR_HELP);
+ std::string description = GetStringAttribute(
+ AccessibilityNodeData::ATTR_DESCRIPTION);
// WebKit annoyingly puts the title in the description if there's no other
// description, which just confuses the rest of the logic. Put it back.
// Now "help" is always the value of the "title" attribute, if present.
+ std::string title_attr;
if (GetHtmlAttribute("title", &title_attr) &&
description == title_attr &&
help.empty()) {
help = description;
description.clear();
- string_attributes_[AccessibilityNodeData::ATTR_DESCRIPTION].clear();
- string_attributes_[AccessibilityNodeData::ATTR_HELP] = help;
}
// Now implement the main logic: the descripion should become the name if
@@ -2854,35 +2898,34 @@ void BrowserAccessibilityWin::PreInitialize() {
if (!description.empty()) {
name_ = description;
description.clear();
- string_attributes_[AccessibilityNodeData::ATTR_DESCRIPTION] = description;
}
if (!help.empty() && description.empty()) {
description = help;
- string_attributes_[AccessibilityNodeData::ATTR_DESCRIPTION] = help;
- string_attributes_[AccessibilityNodeData::ATTR_HELP].clear();
+ help.clear();
}
if (!description.empty() && name_.empty() && !title_elem_id) {
name_ = description;
description.clear();
- string_attributes_[AccessibilityNodeData::ATTR_DESCRIPTION].clear();
}
// If it's a text field, also consider the placeholder.
- string16 placeholder;
- if (role_ == AccessibilityNodeData::ROLE_TEXT_FIELD &&
- HasState(AccessibilityNodeData::STATE_FOCUSABLE) &&
+ std::string placeholder;
+ if (role_ == WebKit::WebAXRoleTextField &&
+ HasState(WebKit::WebAXStateFocusable) &&
GetHtmlAttribute("placeholder", &placeholder)) {
if (name_.empty() && !title_elem_id) {
name_ = placeholder;
} else if (description.empty()) {
description = placeholder;
- string_attributes_[AccessibilityNodeData::ATTR_DESCRIPTION] = description;
}
}
+ SetStringAttribute(AccessibilityNodeData::ATTR_DESCRIPTION, description);
+ SetStringAttribute(AccessibilityNodeData::ATTR_HELP, help);
+
// On Windows, the value of a document should be its url.
- if (role_ == AccessibilityNodeData::ROLE_ROOT_WEB_AREA ||
- role_ == AccessibilityNodeData::ROLE_WEB_AREA) {
+ if (role_ == WebKit::WebAXRoleRootWebArea ||
+ role_ == WebKit::WebAXRoleWebArea) {
GetStringAttribute(AccessibilityNodeData::ATTR_DOC_URL, &value_);
}
@@ -2890,15 +2933,14 @@ void BrowserAccessibilityWin::PreInitialize() {
// WebKit stores the main accessible text in the "value" - swap it so
// that it's the "name".
if (name_.empty() &&
- (role_ == AccessibilityNodeData::ROLE_LISTBOX_OPTION ||
- role_ == AccessibilityNodeData::ROLE_STATIC_TEXT ||
- role_ == AccessibilityNodeData::ROLE_LIST_MARKER)) {
+ (role_ == WebKit::WebAXRoleListBoxOption ||
+ role_ == WebKit::WebAXRoleStaticText ||
+ role_ == WebKit::WebAXRoleListMarker)) {
name_.swap(value_);
}
// 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.
- string16 url;
if (value_.empty() && (ia_state_ & STATE_SYSTEM_LINKED))
GetStringAttribute(AccessibilityNodeData::ATTR_URL, &value_);
@@ -2930,8 +2972,8 @@ void BrowserAccessibilityWin::PostInitialize() {
hypertext_.clear();
for (unsigned int i = 0; i < children().size(); ++i) {
BrowserAccessibility* child = children()[i];
- if (child->role() == AccessibilityNodeData::ROLE_STATIC_TEXT) {
- hypertext_ += child->name();
+ if (child->role() == WebKit::WebAXRoleStaticText) {
+ hypertext_ += UTF8ToUTF16(child->name());
} else {
hyperlink_offset_to_index_[hypertext_.size()] = hyperlinks_.size();
hypertext_ += kEmbeddedCharacter;
@@ -2941,15 +2983,15 @@ void BrowserAccessibilityWin::PostInitialize() {
DCHECK_EQ(hyperlink_offset_to_index_.size(), hyperlinks_.size());
// Fire an event when an alert first appears.
- if (role_ == AccessibilityNodeData::ROLE_ALERT && first_time_)
- manager_->NotifyAccessibilityEvent(AccessibilityNotificationAlert, this);
+ if (role_ == WebKit::WebAXRoleAlert && first_time_)
+ manager_->NotifyAccessibilityEvent(WebKit::WebAXEventAlert, this);
// Fire events if text has changed.
string16 text = TextForIAccessibleText();
if (previous_text_ != text) {
if (!previous_text_.empty() && !text.empty()) {
manager_->NotifyAccessibilityEvent(
- AccessibilityNotificationObjectShow, this);
+ WebKit::WebAXEventShow, this);
}
// TODO(dmazzoni): Look into HIDE events, too.
@@ -2967,7 +3009,7 @@ void BrowserAccessibilityWin::PostInitialize() {
// focus for managed descendants is platform-specific.
// Fire a focus event if the focused descendant in a multi-select
// list box changes.
- if (role_ == AccessibilityNodeData::ROLE_LISTBOX_OPTION &&
+ if (role_ == WebKit::WebAXRoleListBoxOption &&
(ia_state_ & STATE_SYSTEM_FOCUSABLE) &&
(ia_state_ & STATE_SYSTEM_SELECTABLE) &&
(ia_state_ & STATE_SYSTEM_FOCUSED) &&
@@ -3035,7 +3077,7 @@ HRESULT BrowserAccessibilityWin::GetStringAttributeAsBstr(
BSTR* value_bstr) {
string16 str;
- if (!GetStringAttribute(attribute, &str))
+ if (!GetString16Attribute(attribute, &str))
return S_FALSE;
if (str.empty())
@@ -3051,7 +3093,7 @@ void BrowserAccessibilityWin::StringAttributeToIA2(
AccessibilityNodeData::StringAttribute attribute,
const char* ia2_attr) {
string16 value;
- if (GetStringAttribute(attribute, &value))
+ if (GetString16Attribute(attribute, &value))
ia2_attributes_.push_back(ASCIIToUTF16(ia2_attr) + L":" + value);
}
@@ -3069,16 +3111,27 @@ void BrowserAccessibilityWin::IntAttributeToIA2(
AccessibilityNodeData::IntAttribute attribute,
const char* ia2_attr) {
int value;
- if (GetIntAttribute(attribute, &value))
+ if (GetIntAttribute(attribute, &value)) {
ia2_attributes_.push_back(ASCIIToUTF16(ia2_attr) + L":" +
base::IntToString16(value));
+ }
+}
+
+string16 BrowserAccessibilityWin::GetValueText() {
+ float fval;
+ string16 value = UTF8ToUTF16(value_);
+ if (value.empty() &&
+ GetFloatAttribute(AccessibilityNodeData::ATTR_VALUE_FOR_RANGE, &fval)) {
+ value = UTF8ToUTF16(base::DoubleToString(fval));
+ }
+ return value;
}
-const string16& BrowserAccessibilityWin::TextForIAccessibleText() {
+string16 BrowserAccessibilityWin::TextForIAccessibleText() {
if (IsEditableText())
- return value_;
- return (role_ == AccessibilityNodeData::ROLE_STATIC_TEXT) ?
- name_ : hypertext_;
+ return UTF8ToUTF16(value_);
+ return (role_ == WebKit::WebAXRoleStaticText) ?
+ UTF8ToUTF16(name_) : hypertext_;
}
void BrowserAccessibilityWin::HandleSpecialTextOffset(const string16& text,
@@ -3111,8 +3164,10 @@ LONG BrowserAccessibilityWin::FindBoundary(
ui::TextBoundaryDirection direction) {
HandleSpecialTextOffset(text, &start_offset);
ui::TextBoundaryType boundary = IA2TextBoundaryToTextBoundary(ia2_boundary);
+ const std::vector<int32>& line_breaks = GetIntListAttribute(
+ AccessibilityNodeData::ATTR_LINE_BREAKS);
return ui::FindAccessibleTextBoundary(
- text, line_breaks_, boundary, start_offset, direction);
+ text, line_breaks, boundary, start_offset, direction);
}
BrowserAccessibilityWin* BrowserAccessibilityWin::GetFromRendererID(
@@ -3125,99 +3180,95 @@ void BrowserAccessibilityWin::InitRoleAndState() {
ia2_state_ = IA2_STATE_OPAQUE;
ia2_attributes_.clear();
- if (HasState(AccessibilityNodeData::STATE_BUSY))
+ if (HasState(WebKit::WebAXStateBusy))
ia_state_ |= STATE_SYSTEM_BUSY;
- if (HasState(AccessibilityNodeData::STATE_CHECKED))
+ if (HasState(WebKit::WebAXStateChecked))
ia_state_ |= STATE_SYSTEM_CHECKED;
- if (HasState(AccessibilityNodeData::STATE_COLLAPSED))
+ if (HasState(WebKit::WebAXStateCollapsed))
ia_state_ |= STATE_SYSTEM_COLLAPSED;
- if (HasState(AccessibilityNodeData::STATE_EXPANDED))
+ if (HasState(WebKit::WebAXStateExpanded))
ia_state_ |= STATE_SYSTEM_EXPANDED;
- if (HasState(AccessibilityNodeData::STATE_FOCUSABLE))
+ if (HasState(WebKit::WebAXStateFocusable))
ia_state_ |= STATE_SYSTEM_FOCUSABLE;
- if (HasState(AccessibilityNodeData::STATE_HASPOPUP))
+ if (HasState(WebKit::WebAXStateHaspopup))
ia_state_ |= STATE_SYSTEM_HASPOPUP;
- if (HasState(AccessibilityNodeData::STATE_HOTTRACKED))
+ if (HasState(WebKit::WebAXStateHovered))
ia_state_ |= STATE_SYSTEM_HOTTRACKED;
- if (HasState(AccessibilityNodeData::STATE_INDETERMINATE))
+ if (HasState(WebKit::WebAXStateIndeterminate))
ia_state_ |= STATE_SYSTEM_INDETERMINATE;
- if (HasState(AccessibilityNodeData::STATE_INVISIBLE))
+ if (HasState(WebKit::WebAXStateInvisible))
ia_state_ |= STATE_SYSTEM_INVISIBLE;
- if (HasState(AccessibilityNodeData::STATE_LINKED))
+ if (HasState(WebKit::WebAXStateLinked))
ia_state_ |= STATE_SYSTEM_LINKED;
- if (HasState(AccessibilityNodeData::STATE_MULTISELECTABLE)) {
+ if (HasState(WebKit::WebAXStateMultiselectable)) {
ia_state_ |= STATE_SYSTEM_EXTSELECTABLE;
ia_state_ |= STATE_SYSTEM_MULTISELECTABLE;
}
// TODO(ctguil): Support STATE_SYSTEM_EXTSELECTABLE/accSelect.
- if (HasState(AccessibilityNodeData::STATE_OFFSCREEN))
+ if (HasState(WebKit::WebAXStateOffscreen))
ia_state_ |= STATE_SYSTEM_OFFSCREEN;
- if (HasState(AccessibilityNodeData::STATE_PRESSED))
+ if (HasState(WebKit::WebAXStatePressed))
ia_state_ |= STATE_SYSTEM_PRESSED;
- if (HasState(AccessibilityNodeData::STATE_PROTECTED))
+ if (HasState(WebKit::WebAXStateProtected))
ia_state_ |= STATE_SYSTEM_PROTECTED;
- if (HasState(AccessibilityNodeData::STATE_REQUIRED))
+ if (HasState(WebKit::WebAXStateRequired))
ia2_state_ |= IA2_STATE_REQUIRED;
- if (HasState(AccessibilityNodeData::STATE_SELECTABLE))
+ if (HasState(WebKit::WebAXStateSelectable))
ia_state_ |= STATE_SYSTEM_SELECTABLE;
- if (HasState(AccessibilityNodeData::STATE_SELECTED))
+ if (HasState(WebKit::WebAXStateSelected))
ia_state_ |= STATE_SYSTEM_SELECTED;
- if (HasState(AccessibilityNodeData::STATE_TRAVERSED))
+ if (HasState(WebKit::WebAXStateVisited))
ia_state_ |= STATE_SYSTEM_TRAVERSED;
- if (HasState(AccessibilityNodeData::STATE_UNAVAILABLE))
+ if (!HasState(WebKit::WebAXStateEnabled))
ia_state_ |= STATE_SYSTEM_UNAVAILABLE;
- if (HasState(AccessibilityNodeData::STATE_VERTICAL)) {
+ if (HasState(WebKit::WebAXStateVertical)) {
ia2_state_ |= IA2_STATE_VERTICAL;
} else {
ia2_state_ |= IA2_STATE_HORIZONTAL;
}
- if (HasState(AccessibilityNodeData::STATE_VISITED))
+ if (HasState(WebKit::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(AccessibilityNodeData::STATE_READONLY))
+ if (!HasState(WebKit::WebAXStateReadonly))
ia2_state_ |= IA2_STATE_EDITABLE;
string16 invalid;
if (GetHtmlAttribute("aria-invalid", &invalid))
ia2_state_ |= IA2_STATE_INVALID_ENTRY;
- bool mixed = false;
- GetBoolAttribute(AccessibilityNodeData::ATTR_BUTTON_MIXED, &mixed);
- if (mixed)
+ if (GetBoolAttribute(AccessibilityNodeData::ATTR_BUTTON_MIXED))
ia_state_ |= STATE_SYSTEM_MIXED;
- bool editable = false;
- GetBoolAttribute(AccessibilityNodeData::ATTR_CAN_SET_VALUE, &editable);
- if (editable)
+ if (GetBoolAttribute(AccessibilityNodeData::ATTR_CAN_SET_VALUE))
ia2_state_ |= IA2_STATE_EDITABLE;
- string16 html_tag;
- GetStringAttribute(AccessibilityNodeData::ATTR_HTML_TAG, &html_tag);
+ string16 html_tag = GetString16Attribute(
+ AccessibilityNodeData::ATTR_HTML_TAG);
ia_role_ = 0;
ia2_role_ = 0;
switch (role_) {
- case AccessibilityNodeData::ROLE_ALERT:
+ case WebKit::WebAXRoleAlert:
ia_role_ = ROLE_SYSTEM_ALERT;
break;
- case AccessibilityNodeData::ROLE_ALERT_DIALOG:
+ case WebKit::WebAXRoleAlertDialog:
ia_role_ = ROLE_SYSTEM_DIALOG;
break;
- case AccessibilityNodeData::ROLE_APPLICATION:
+ case WebKit::WebAXRoleApplication:
ia_role_ = ROLE_SYSTEM_APPLICATION;
break;
- case AccessibilityNodeData::ROLE_ARTICLE:
+ case WebKit::WebAXRoleArticle:
ia_role_ = ROLE_SYSTEM_GROUPING;
ia2_role_ = IA2_ROLE_SECTION;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_BUSY_INDICATOR:
+ case WebKit::WebAXRoleBusyIndicator:
ia_role_ = ROLE_SYSTEM_ANIMATION;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_BUTTON:
+ case WebKit::WebAXRoleButton:
ia_role_ = ROLE_SYSTEM_PUSHBUTTON;
bool is_aria_pressed_defined;
bool is_mixed;
@@ -3228,87 +3279,88 @@ void BrowserAccessibilityWin::InitRoleAndState() {
if (is_mixed)
ia_state_ |= STATE_SYSTEM_MIXED;
break;
- case AccessibilityNodeData::ROLE_CANVAS:
- ia_role_ = ROLE_SYSTEM_GRAPHIC;
- break;
- case AccessibilityNodeData::ROLE_CANVAS_WITH_FALLBACK_CONTENT:
- role_name_ = L"canvas";
- ia2_role_ = IA2_ROLE_CANVAS;
+ case WebKit::WebAXRoleCanvas:
+ if (GetBoolAttribute(AccessibilityNodeData::ATTR_CANVAS_HAS_FALLBACK)) {
+ role_name_ = L"canvas";
+ ia2_role_ = IA2_ROLE_CANVAS;
+ } else {
+ ia_role_ = ROLE_SYSTEM_GRAPHIC;
+ }
break;
- case AccessibilityNodeData::ROLE_CELL:
+ case WebKit::WebAXRoleCell:
ia_role_ = ROLE_SYSTEM_CELL;
break;
- case AccessibilityNodeData::ROLE_CHECKBOX:
+ case WebKit::WebAXRoleCheckBox:
ia_role_ = ROLE_SYSTEM_CHECKBUTTON;
break;
- case AccessibilityNodeData::ROLE_COLOR_WELL:
+ case WebKit::WebAXRoleColorWell:
ia_role_ = ROLE_SYSTEM_CLIENT;
ia2_role_ = IA2_ROLE_COLOR_CHOOSER;
break;
- case AccessibilityNodeData::ROLE_COLUMN:
+ case WebKit::WebAXRoleColumn:
ia_role_ = ROLE_SYSTEM_COLUMN;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_COLUMN_HEADER:
+ case WebKit::WebAXRoleColumnHeader:
ia_role_ = ROLE_SYSTEM_COLUMNHEADER;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_COMBO_BOX:
+ case WebKit::WebAXRoleComboBox:
ia_role_ = ROLE_SYSTEM_COMBOBOX;
break;
- case AccessibilityNodeData::ROLE_DIV:
+ case WebKit::WebAXRoleDiv:
role_name_ = L"div";
ia2_role_ = IA2_ROLE_SECTION;
break;
- case AccessibilityNodeData::ROLE_DEFINITION:
+ case WebKit::WebAXRoleDefinition:
role_name_ = html_tag;
ia2_role_ = IA2_ROLE_PARAGRAPH;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_DESCRIPTION_LIST_DETAIL:
+ case WebKit::WebAXRoleDescriptionListDetail:
role_name_ = html_tag;
ia2_role_ = IA2_ROLE_PARAGRAPH;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_DESCRIPTION_LIST_TERM:
+ case WebKit::WebAXRoleDescriptionListTerm:
ia_role_ = ROLE_SYSTEM_LISTITEM;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_DIALOG:
+ case WebKit::WebAXRoleDialog:
ia_role_ = ROLE_SYSTEM_DIALOG;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_DISCLOSURE_TRIANGLE:
+ case WebKit::WebAXRoleDisclosureTriangle:
ia_role_ = ROLE_SYSTEM_OUTLINEBUTTON;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_DOCUMENT:
- case AccessibilityNodeData::ROLE_ROOT_WEB_AREA:
- case AccessibilityNodeData::ROLE_WEB_AREA:
+ case WebKit::WebAXRoleDocument:
+ case WebKit::WebAXRoleRootWebArea:
+ case WebKit::WebAXRoleWebArea:
ia_role_ = ROLE_SYSTEM_DOCUMENT;
ia_state_ |= STATE_SYSTEM_READONLY;
ia_state_ |= STATE_SYSTEM_FOCUSABLE;
break;
- case AccessibilityNodeData::ROLE_EDITABLE_TEXT:
+ case WebKit::WebAXRoleEditableText:
ia_role_ = ROLE_SYSTEM_TEXT;
ia2_state_ |= IA2_STATE_SINGLE_LINE;
ia2_state_ |= IA2_STATE_EDITABLE;
break;
- case AccessibilityNodeData::ROLE_FORM:
+ case WebKit::WebAXRoleForm:
role_name_ = L"form";
ia2_role_ = IA2_ROLE_FORM;
break;
- case AccessibilityNodeData::ROLE_FOOTER:
+ case WebKit::WebAXRoleFooter:
ia_role_ = IA2_ROLE_FOOTER;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_GRID:
+ case WebKit::WebAXRoleGrid:
ia_role_ = ROLE_SYSTEM_TABLE;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_GROUP: {
- string16 aria_role;
- GetStringAttribute(AccessibilityNodeData::ATTR_ROLE, &aria_role);
+ case WebKit::WebAXRoleGroup: {
+ string16 aria_role = GetString16Attribute(
+ AccessibilityNodeData::ATTR_ROLE);
if (aria_role == L"group" || html_tag == L"fieldset") {
ia_role_ = ROLE_SYSTEM_GROUPING;
} else if (html_tag == L"li") {
@@ -3323,192 +3375,190 @@ void BrowserAccessibilityWin::InitRoleAndState() {
ia_state_ |= STATE_SYSTEM_READONLY;
break;
}
- case AccessibilityNodeData::ROLE_GROW_AREA:
+ case WebKit::WebAXRoleGrowArea:
ia_role_ = ROLE_SYSTEM_GRIP;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_HEADING:
+ case WebKit::WebAXRoleHeading:
role_name_ = html_tag;
ia2_role_ = IA2_ROLE_HEADING;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_HORIZONTAL_RULE:
+ case WebKit::WebAXRoleHorizontalRule:
ia_role_ = ROLE_SYSTEM_SEPARATOR;
break;
- case AccessibilityNodeData::ROLE_IMAGE:
+ case WebKit::WebAXRoleImage:
ia_role_ = ROLE_SYSTEM_GRAPHIC;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_IMAGE_MAP:
+ case WebKit::WebAXRoleImageMap:
role_name_ = html_tag;
ia2_role_ = IA2_ROLE_IMAGE_MAP;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_IMAGE_MAP_LINK:
+ case WebKit::WebAXRoleImageMapLink:
ia_role_ = ROLE_SYSTEM_LINK;
ia_state_ |= STATE_SYSTEM_LINKED;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_LABEL:
+ case WebKit::WebAXRoleLabel:
ia_role_ = ROLE_SYSTEM_TEXT;
ia2_role_ = IA2_ROLE_LABEL;
break;
- case AccessibilityNodeData::ROLE_LANDMARK_APPLICATION:
- case AccessibilityNodeData::ROLE_LANDMARK_BANNER:
- case AccessibilityNodeData::ROLE_LANDMARK_COMPLEMENTARY:
- case AccessibilityNodeData::ROLE_LANDMARK_CONTENTINFO:
- case AccessibilityNodeData::ROLE_LANDMARK_MAIN:
- case AccessibilityNodeData::ROLE_LANDMARK_NAVIGATION:
- case AccessibilityNodeData::ROLE_LANDMARK_SEARCH:
+ case WebKit::WebAXRoleBanner:
+ case WebKit::WebAXRoleComplementary:
+ case WebKit::WebAXRoleContentInfo:
+ case WebKit::WebAXRoleMain:
+ case WebKit::WebAXRoleNavigation:
+ case WebKit::WebAXRoleSearch:
ia_role_ = ROLE_SYSTEM_GROUPING;
ia2_role_ = IA2_ROLE_SECTION;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_LINK:
- case AccessibilityNodeData::ROLE_WEBCORE_LINK:
+ case WebKit::WebAXRoleLink:
ia_role_ = ROLE_SYSTEM_LINK;
ia_state_ |= STATE_SYSTEM_LINKED;
break;
- case AccessibilityNodeData::ROLE_LIST:
+ case WebKit::WebAXRoleList:
ia_role_ = ROLE_SYSTEM_LIST;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_LISTBOX:
+ case WebKit::WebAXRoleListBox:
ia_role_ = ROLE_SYSTEM_LIST;
break;
- case AccessibilityNodeData::ROLE_LISTBOX_OPTION:
+ case WebKit::WebAXRoleListBoxOption:
ia_role_ = ROLE_SYSTEM_LISTITEM;
if (ia_state_ & STATE_SYSTEM_SELECTABLE) {
ia_state_ |= STATE_SYSTEM_FOCUSABLE;
- if (HasState(AccessibilityNodeData::STATE_FOCUSED))
+ if (HasState(WebKit::WebAXStateFocused))
ia_state_ |= STATE_SYSTEM_FOCUSED;
}
break;
- case AccessibilityNodeData::ROLE_LIST_ITEM:
+ case WebKit::WebAXRoleListItem:
ia_role_ = ROLE_SYSTEM_LISTITEM;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_LIST_MARKER:
+ case WebKit::WebAXRoleListMarker:
ia_role_ = ROLE_SYSTEM_TEXT;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_MATH:
+ case WebKit::WebAXRoleMath:
ia_role_ = ROLE_SYSTEM_EQUATION;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_MENU:
- case AccessibilityNodeData::ROLE_MENU_BUTTON:
+ case WebKit::WebAXRoleMenu:
+ case WebKit::WebAXRoleMenuButton:
ia_role_ = ROLE_SYSTEM_MENUPOPUP;
break;
- case AccessibilityNodeData::ROLE_MENU_BAR:
+ case WebKit::WebAXRoleMenuBar:
ia_role_ = ROLE_SYSTEM_MENUBAR;
break;
- case AccessibilityNodeData::ROLE_MENU_ITEM:
+ case WebKit::WebAXRoleMenuItem:
ia_role_ = ROLE_SYSTEM_MENUITEM;
break;
- case AccessibilityNodeData::ROLE_MENU_LIST_POPUP:
+ case WebKit::WebAXRoleMenuListPopup:
ia_role_ = ROLE_SYSTEM_CLIENT;
break;
- case AccessibilityNodeData::ROLE_MENU_LIST_OPTION:
+ case WebKit::WebAXRoleMenuListOption:
ia_role_ = ROLE_SYSTEM_LISTITEM;
if (ia_state_ & STATE_SYSTEM_SELECTABLE) {
ia_state_ |= STATE_SYSTEM_FOCUSABLE;
- if (HasState(AccessibilityNodeData::STATE_FOCUSED))
+ if (HasState(WebKit::WebAXStateFocused))
ia_state_ |= STATE_SYSTEM_FOCUSED;
}
break;
- case AccessibilityNodeData::ROLE_NOTE:
+ case WebKit::WebAXRoleNote:
ia_role_ = ROLE_SYSTEM_GROUPING;
ia2_role_ = IA2_ROLE_NOTE;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_OUTLINE:
+ case WebKit::WebAXRoleOutline:
ia_role_ = ROLE_SYSTEM_OUTLINE;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_PARAGRAPH:
+ case WebKit::WebAXRoleParagraph:
role_name_ = L"P";
ia2_role_ = IA2_ROLE_PARAGRAPH;
break;
- case AccessibilityNodeData::ROLE_POPUP_BUTTON:
+ case WebKit::WebAXRolePopUpButton:
if (html_tag == L"select") {
ia_role_ = ROLE_SYSTEM_COMBOBOX;
} else {
ia_role_ = ROLE_SYSTEM_BUTTONMENU;
}
break;
- case AccessibilityNodeData::ROLE_PROGRESS_INDICATOR:
+ case WebKit::WebAXRoleProgressIndicator:
ia_role_ = ROLE_SYSTEM_PROGRESSBAR;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_RADIO_BUTTON:
+ case WebKit::WebAXRoleRadioButton:
ia_role_ = ROLE_SYSTEM_RADIOBUTTON;
break;
- case AccessibilityNodeData::ROLE_RADIO_GROUP:
+ case WebKit::WebAXRoleRadioGroup:
ia_role_ = ROLE_SYSTEM_GROUPING;
ia2_role_ = IA2_ROLE_SECTION;
break;
- case AccessibilityNodeData::ROLE_REGION:
+ case WebKit::WebAXRoleRegion:
ia_role_ = ROLE_SYSTEM_GROUPING;
ia2_role_ = IA2_ROLE_SECTION;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_ROW:
+ case WebKit::WebAXRoleRow:
ia_role_ = ROLE_SYSTEM_ROW;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_ROW_HEADER:
+ case WebKit::WebAXRoleRowHeader:
ia_role_ = ROLE_SYSTEM_ROWHEADER;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_RULER:
+ case WebKit::WebAXRoleRuler:
ia_role_ = ROLE_SYSTEM_CLIENT;
ia2_role_ = IA2_ROLE_RULER;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_SCROLLAREA:
+ case WebKit::WebAXRoleScrollArea:
ia_role_ = ROLE_SYSTEM_CLIENT;
ia2_role_ = IA2_ROLE_SCROLL_PANE;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_SCROLLBAR:
+ case WebKit::WebAXRoleScrollBar:
ia_role_ = ROLE_SYSTEM_SCROLLBAR;
break;
- case AccessibilityNodeData::ROLE_SLIDER:
+ case WebKit::WebAXRoleSlider:
ia_role_ = ROLE_SYSTEM_SLIDER;
break;
- case AccessibilityNodeData::ROLE_SPIN_BUTTON:
+ case WebKit::WebAXRoleSpinButton:
ia_role_ = ROLE_SYSTEM_SPINBUTTON;
break;
- case AccessibilityNodeData::ROLE_SPIN_BUTTON_PART:
+ case WebKit::WebAXRoleSpinButtonPart:
ia_role_ = ROLE_SYSTEM_PUSHBUTTON;
break;
- case AccessibilityNodeData::ROLE_SPLIT_GROUP:
+ case WebKit::WebAXRoleSplitGroup:
ia_role_ = ROLE_SYSTEM_CLIENT;
ia2_role_ = IA2_ROLE_SPLIT_PANE;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_ANNOTATION:
- case AccessibilityNodeData::ROLE_STATIC_TEXT:
+ case WebKit::WebAXRoleAnnotation:
+ case WebKit::WebAXRoleStaticText:
ia_role_ = ROLE_SYSTEM_TEXT;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_STATUS:
+ case WebKit::WebAXRoleStatus:
ia_role_ = ROLE_SYSTEM_STATUSBAR;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_SPLITTER:
+ case WebKit::WebAXRoleSplitter:
ia_role_ = ROLE_SYSTEM_SEPARATOR;
break;
- case AccessibilityNodeData::ROLE_SVG_ROOT:
+ case WebKit::WebAXRoleSVGRoot:
ia_role_ = ROLE_SYSTEM_GRAPHIC;
break;
- case AccessibilityNodeData::ROLE_TAB:
+ case WebKit::WebAXRoleTab:
ia_role_ = ROLE_SYSTEM_PAGETAB;
break;
- case AccessibilityNodeData::ROLE_TABLE: {
- string16 aria_role;
- GetStringAttribute(AccessibilityNodeData::ATTR_ROLE, &aria_role);
+ case WebKit::WebAXRoleTable: {
+ string16 aria_role = GetString16Attribute(
+ AccessibilityNodeData::ATTR_ROLE);
if (aria_role == L"treegrid") {
ia_role_ = ROLE_SYSTEM_OUTLINE;
} else {
@@ -3517,81 +3567,77 @@ void BrowserAccessibilityWin::InitRoleAndState() {
}
break;
}
- case AccessibilityNodeData::ROLE_TABLE_HEADER_CONTAINER:
+ case WebKit::WebAXRoleTableHeaderContainer:
ia_role_ = ROLE_SYSTEM_GROUPING;
ia2_role_ = IA2_ROLE_SECTION;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_TAB_GROUP_UNUSED:
- NOTREACHED();
- ia_role_ = ROLE_SYSTEM_PAGETABLIST;
- break;
- case AccessibilityNodeData::ROLE_TAB_LIST:
+ case WebKit::WebAXRoleTabList:
ia_role_ = ROLE_SYSTEM_PAGETABLIST;
break;
- case AccessibilityNodeData::ROLE_TAB_PANEL:
+ case WebKit::WebAXRoleTabPanel:
ia_role_ = ROLE_SYSTEM_PROPERTYPAGE;
break;
- case AccessibilityNodeData::ROLE_TOGGLE_BUTTON:
+ case WebKit::WebAXRoleToggleButton:
ia_role_ = ROLE_SYSTEM_PUSHBUTTON;
ia2_role_ = IA2_ROLE_TOGGLE_BUTTON;
break;
- case AccessibilityNodeData::ROLE_TEXTAREA:
+ case WebKit::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 AccessibilityNodeData::ROLE_TEXT_FIELD:
+ case WebKit::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 AccessibilityNodeData::ROLE_TIMER:
+ case WebKit::WebAXRoleTimer:
ia_role_ = ROLE_SYSTEM_CLOCK;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_TOOLBAR:
+ case WebKit::WebAXRoleToolbar:
ia_role_ = ROLE_SYSTEM_TOOLBAR;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_TOOLTIP:
+ case WebKit::WebAXRoleUserInterfaceTooltip:
ia_role_ = ROLE_SYSTEM_TOOLTIP;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_TREE:
+ case WebKit::WebAXRoleTree:
ia_role_ = ROLE_SYSTEM_OUTLINE;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_TREE_GRID:
+ case WebKit::WebAXRoleTreeGrid:
ia_role_ = ROLE_SYSTEM_OUTLINE;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_TREE_ITEM:
+ case WebKit::WebAXRoleTreeItem:
ia_role_ = ROLE_SYSTEM_OUTLINEITEM;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case AccessibilityNodeData::ROLE_WINDOW:
+ case WebKit::WebAXRoleWindow:
ia_role_ = ROLE_SYSTEM_WINDOW;
break;
// TODO(dmazzoni): figure out the proper MSAA role for all of these.
- case AccessibilityNodeData::ROLE_BROWSER:
- case AccessibilityNodeData::ROLE_DIRECTORY:
- case AccessibilityNodeData::ROLE_DRAWER:
- case AccessibilityNodeData::ROLE_HELP_TAG:
- case AccessibilityNodeData::ROLE_IGNORED:
- case AccessibilityNodeData::ROLE_INCREMENTOR:
- case AccessibilityNodeData::ROLE_LOG:
- case AccessibilityNodeData::ROLE_MARQUEE:
- case AccessibilityNodeData::ROLE_MATTE:
- case AccessibilityNodeData::ROLE_PRESENTATIONAL:
- case AccessibilityNodeData::ROLE_RULER_MARKER:
- case AccessibilityNodeData::ROLE_SHEET:
- case AccessibilityNodeData::ROLE_SLIDER_THUMB:
- case AccessibilityNodeData::ROLE_SYSTEM_WIDE:
- case AccessibilityNodeData::ROLE_VALUE_INDICATOR:
+ 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:
default:
ia_role_ = ROLE_SYSTEM_CLIENT;
break;
@@ -3603,15 +3649,13 @@ 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(AccessibilityNodeData::STATE_FOCUSABLE) &&
+ if (HasState(WebKit::WebAXStateFocusable) &&
ia_role_ != ROLE_SYSTEM_DOCUMENT) {
ia_state_ &= ~(STATE_SYSTEM_READONLY);
}
- if (!HasState(AccessibilityNodeData::STATE_READONLY))
+ if (!HasState(WebKit::WebAXStateReadonly))
ia_state_ &= ~(STATE_SYSTEM_READONLY);
- bool aria_readonly = false;
- GetBoolAttribute(AccessibilityNodeData::ATTR_ARIA_READONLY, &aria_readonly);
- if (aria_readonly)
+ if (GetBoolAttribute(AccessibilityNodeData::ATTR_ARIA_READONLY))
ia_state_ |= STATE_SYSTEM_READONLY;
// The role should always be set.
diff --git a/chromium/content/browser/accessibility/browser_accessibility_win.h b/chromium/content/browser/accessibility/browser_accessibility_win.h
index b6599325da8..db8040e3161 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_win.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_win.h
@@ -771,6 +771,7 @@ BrowserAccessibilityWin
// Accessors.
int32 ia_role() const { return ia_role_; }
int32 ia_state() const { return ia_state_; }
+ const 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 {
@@ -816,9 +817,13 @@ BrowserAccessibilityWin
void IntAttributeToIA2(AccessibilityNodeData::IntAttribute attribute,
const char* ia2_attr);
+ // Get the value text, which might come from the floating-point
+ // value for some roles.
+ 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.
- const string16& TextForIAccessibleText();
+ string16 TextForIAccessibleText();
// If offset is a member of IA2TextSpecialOffsets this function updates the
// value of offset and returns, otherwise offset remains unchanged.
@@ -847,6 +852,7 @@ BrowserAccessibilityWin
// IAccessible role and state.
int32 ia_role_;
int32 ia_state_;
+ string16 role_name_;
// IAccessible2 role and state.
int32 ia2_role_;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc b/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
index 98a5d404a43..c623e257803 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "base/memory/scoped_ptr.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/win/scoped_bstr.h"
#include "base/win/scoped_comptr.h"
#include "base/win/scoped_variant.h"
@@ -113,20 +114,20 @@ TEST_F(BrowserAccessibilityTest, TestNoLeaks) {
// BrowserAccessibilityManager.
AccessibilityNodeData button;
button.id = 2;
- button.name = L"Button";
- button.role = AccessibilityNodeData::ROLE_BUTTON;
+ button.SetName("Button");
+ button.role = WebKit::WebAXRoleButton;
button.state = 0;
AccessibilityNodeData checkbox;
checkbox.id = 3;
- checkbox.name = L"Checkbox";
- checkbox.role = AccessibilityNodeData::ROLE_CHECKBOX;
+ checkbox.SetName("Checkbox");
+ checkbox.role = WebKit::WebAXRoleCheckBox;
checkbox.state = 0;
AccessibilityNodeData root;
root.id = 1;
- root.name = L"Document";
- root.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA;
+ root.SetName("Document");
+ root.role = WebKit::WebAXRoleRootWebArea;
root.state = 0;
root.child_ids.push_back(2);
root.child_ids.push_back(3);
@@ -182,14 +183,14 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChange) {
// BrowserAccessibilityManager.
AccessibilityNodeData text;
text.id = 2;
- text.role = AccessibilityNodeData::ROLE_STATIC_TEXT;
- text.name = L"old text";
+ text.role = WebKit::WebAXRoleStaticText;
+ text.SetName("old text");
text.state = 0;
AccessibilityNodeData root;
root.id = 1;
- root.name = L"Document";
- root.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA;
+ root.SetName("Document");
+ root.role = WebKit::WebAXRoleRootWebArea;
root.state = 0;
root.child_ids.push_back(2);
@@ -225,14 +226,18 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChange) {
text_accessible.Release();
// Notify the BrowserAccessibilityManager that the text child has changed.
- text.name = L"new text";
- AccessibilityHostMsg_NotificationParams param;
- param.notification_type = AccessibilityNotificationChildrenChanged;
- param.nodes.push_back(text);
- param.id = text.id;
- std::vector<AccessibilityHostMsg_NotificationParams> notifications;
- notifications.push_back(param);
- manager->OnAccessibilityNotifications(notifications);
+ AccessibilityNodeData text2;
+ text2.id = 2;
+ text2.role = WebKit::WebAXRoleStaticText;
+ text2.SetName("new text");
+ text2.SetName("old text");
+ AccessibilityHostMsg_EventParams param;
+ param.event_type = WebKit::WebAXEventChildrenChanged;
+ param.nodes.push_back(text2);
+ param.id = text2.id;
+ std::vector<AccessibilityHostMsg_EventParams> events;
+ events.push_back(param);
+ manager->OnAccessibilityEvents(events);
// Query for the text IAccessible and verify that it now returns "new text"
// as its value.
@@ -262,17 +267,17 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChangeNoLeaks) {
// BrowserAccessibilityManager.
AccessibilityNodeData div;
div.id = 2;
- div.role = AccessibilityNodeData::ROLE_GROUP;
+ div.role = WebKit::WebAXRoleGroup;
div.state = 0;
AccessibilityNodeData text3;
text3.id = 3;
- text3.role = AccessibilityNodeData::ROLE_STATIC_TEXT;
+ text3.role = WebKit::WebAXRoleStaticText;
text3.state = 0;
AccessibilityNodeData text4;
text4.id = 4;
- text4.role = AccessibilityNodeData::ROLE_STATIC_TEXT;
+ text4.role = WebKit::WebAXRoleStaticText;
text4.state = 0;
div.child_ids.push_back(3);
@@ -280,7 +285,7 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChangeNoLeaks) {
AccessibilityNodeData root;
root.id = 1;
- root.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA;
+ root.role = WebKit::WebAXRoleRootWebArea;
root.state = 0;
root.child_ids.push_back(2);
@@ -298,13 +303,13 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChangeNoLeaks) {
// Notify the BrowserAccessibilityManager that the div node and its children
// were removed and ensure that only one BrowserAccessibility instance exists.
root.child_ids.clear();
- AccessibilityHostMsg_NotificationParams param;
- param.notification_type = AccessibilityNotificationChildrenChanged;
+ AccessibilityHostMsg_EventParams param;
+ param.event_type = WebKit::WebAXEventChildrenChanged;
param.nodes.push_back(root);
param.id = root.id;
- std::vector<AccessibilityHostMsg_NotificationParams> notifications;
- notifications.push_back(param);
- manager->OnAccessibilityNotifications(notifications);
+ std::vector<AccessibilityHostMsg_EventParams> events;
+ events.push_back(param);
+ manager->OnAccessibilityEvents(events);
ASSERT_EQ(1, CountedBrowserAccessibility::num_instances());
// Delete the manager and test that all BrowserAccessibility instances are
@@ -314,16 +319,21 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChangeNoLeaks) {
}
TEST_F(BrowserAccessibilityTest, TestTextBoundaries) {
+ std::string text1_value = "One two three.\nFour five six.";
+
AccessibilityNodeData text1;
text1.id = 11;
- text1.role = AccessibilityNodeData::ROLE_TEXT_FIELD;
+ text1.role = WebKit::WebAXRoleTextField;
text1.state = 0;
- text1.value = L"One two three.\nFour five six.";
- text1.line_breaks.push_back(15);
+ text1.AddStringAttribute(AccessibilityNodeData::ATTR_VALUE, text1_value);
+ std::vector<int32> line_breaks;
+ line_breaks.push_back(15);
+ text1.AddIntListAttribute(
+ AccessibilityNodeData::ATTR_LINE_BREAKS, line_breaks);
AccessibilityNodeData root;
root.id = 1;
- root.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA;
+ root.role = WebKit::WebAXRoleRootWebArea;
root.state = 0;
root.child_ids.push_back(11);
@@ -344,7 +354,7 @@ TEST_F(BrowserAccessibilityTest, TestTextBoundaries) {
base::win::ScopedBstr text;
ASSERT_EQ(S_OK, text1_obj->get_text(0, text1_len, text.Receive()));
- ASSERT_EQ(text1.value, string16(text));
+ ASSERT_EQ(text1_value, base::UTF16ToUTF8(string16(text)));
text.Reset();
ASSERT_EQ(S_OK, text1_obj->get_text(0, 4, text.Receive()));
@@ -405,22 +415,25 @@ TEST_F(BrowserAccessibilityTest, TestTextBoundaries) {
}
TEST_F(BrowserAccessibilityTest, TestSimpleHypertext) {
+ const std::string text1_name = "One two three.";
+ const std::string text2_name = " Four five six.";
+
AccessibilityNodeData text1;
text1.id = 11;
- text1.role = AccessibilityNodeData::ROLE_STATIC_TEXT;
- text1.state = 1 << AccessibilityNodeData::STATE_READONLY;
- text1.name = L"One two three.";
+ text1.role = WebKit::WebAXRoleStaticText;
+ text1.state = 1 << WebKit::WebAXStateReadonly;
+ text1.SetName(text1_name);
AccessibilityNodeData text2;
text2.id = 12;
- text2.role = AccessibilityNodeData::ROLE_STATIC_TEXT;
- text2.state = 1 << AccessibilityNodeData::STATE_READONLY;
- text2.name = L" Four five six.";
+ text2.role = WebKit::WebAXRoleStaticText;
+ text2.state = 1 << WebKit::WebAXStateReadonly;
+ text2.SetName(text2_name);
AccessibilityNodeData root;
root.id = 1;
- root.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA;
- root.state = 1 << AccessibilityNodeData::STATE_READONLY;
+ root.role = WebKit::WebAXRoleRootWebArea;
+ root.state = 1 << WebKit::WebAXStateReadonly;
root.child_ids.push_back(11);
root.child_ids.push_back(12);
@@ -439,7 +452,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, string16(text));
+ EXPECT_EQ(text1_name + text2_name, base::UTF16ToUTF8(string16(text)));
long hyperlink_count;
ASSERT_EQ(S_OK, root_obj->get_nHyperlinks(&hyperlink_count));
@@ -468,42 +481,47 @@ TEST_F(BrowserAccessibilityTest, TestSimpleHypertext) {
}
TEST_F(BrowserAccessibilityTest, TestComplexHypertext) {
+ const std::string text1_name = "One two three.";
+ const std::string text2_name = " Four five six.";
+ const std::string button1_text_name = "red";
+ const std::string link1_text_name = "blue";
+
AccessibilityNodeData text1;
text1.id = 11;
- text1.role = AccessibilityNodeData::ROLE_STATIC_TEXT;
- text1.state = 1 << AccessibilityNodeData::STATE_READONLY;
- text1.name = L"One two three.";
+ text1.role = WebKit::WebAXRoleStaticText;
+ text1.state = 1 << WebKit::WebAXStateReadonly;
+ text1.SetName(text1_name);
AccessibilityNodeData text2;
text2.id = 12;
- text2.role = AccessibilityNodeData::ROLE_STATIC_TEXT;
- text2.state = 1 << AccessibilityNodeData::STATE_READONLY;
- text2.name = L" Four five six.";
+ text2.role = WebKit::WebAXRoleStaticText;
+ text2.state = 1 << WebKit::WebAXStateReadonly;
+ text2.SetName(text2_name);
AccessibilityNodeData button1, button1_text;
button1.id = 13;
button1_text.id = 15;
- button1_text.name = L"red";
- button1.role = AccessibilityNodeData::ROLE_BUTTON;
- button1_text.role = AccessibilityNodeData::ROLE_STATIC_TEXT;
- button1.state = 1 << AccessibilityNodeData::STATE_READONLY;
- button1_text.state = 1 << AccessibilityNodeData::STATE_READONLY;
+ 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.child_ids.push_back(15);
AccessibilityNodeData link1, link1_text;
link1.id = 14;
link1_text.id = 16;
- link1_text.name = L"blue";
- link1.role = AccessibilityNodeData::ROLE_LINK;
- link1_text.role = AccessibilityNodeData::ROLE_STATIC_TEXT;
- link1.state = 1 << AccessibilityNodeData::STATE_READONLY;
- link1_text.state = 1 << AccessibilityNodeData::STATE_READONLY;
+ 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.child_ids.push_back(16);
AccessibilityNodeData root;
root.id = 1;
- root.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA;
- root.state = 1 << AccessibilityNodeData::STATE_READONLY;
+ root.role = WebKit::WebAXRoleRootWebArea;
+ root.state = 1 << WebKit::WebAXStateReadonly;
root.child_ids.push_back(11);
root.child_ids.push_back(13);
root.child_ids.push_back(12);
@@ -527,8 +545,10 @@ TEST_F(BrowserAccessibilityTest, TestComplexHypertext) {
base::win::ScopedBstr text;
ASSERT_EQ(S_OK, root_obj->get_text(0, text_len, text.Receive()));
- const string16 embed = BrowserAccessibilityWin::kEmbeddedCharacter;
- EXPECT_EQ(text1.name + embed + text2.name + embed, string16(text));
+ const std::string embed = base::UTF16ToUTF8(
+ BrowserAccessibilityWin::kEmbeddedCharacter);
+ EXPECT_EQ(text1_name + embed + text2_name + embed,
+ UTF16ToUTF8(string16(text)));
text.Reset();
long hyperlink_count;
@@ -545,7 +565,8 @@ TEST_F(BrowserAccessibilityTest, TestComplexHypertext) {
EXPECT_EQ(S_OK,
hyperlink.QueryInterface<IAccessibleText>(hypertext.Receive()));
EXPECT_EQ(S_OK, hypertext->get_text(0, 3, text.Receive()));
- EXPECT_STREQ(L"red", text);
+ EXPECT_STREQ(button1_text_name.c_str(),
+ base::UTF16ToUTF8(string16(text)).c_str());
text.Reset();
hyperlink.Release();
hypertext.Release();
@@ -554,7 +575,8 @@ TEST_F(BrowserAccessibilityTest, TestComplexHypertext) {
EXPECT_EQ(S_OK,
hyperlink.QueryInterface<IAccessibleText>(hypertext.Receive()));
EXPECT_EQ(S_OK, hypertext->get_text(0, 4, text.Receive()));
- EXPECT_STREQ(L"blue", text);
+ EXPECT_STREQ(link1_text_name.c_str(),
+ base::UTF16ToUTF8(string16(text)).c_str());
text.Reset();
hyperlink.Release();
hypertext.Release();
@@ -579,8 +601,9 @@ TEST_F(BrowserAccessibilityTest, TestCreateEmptyDocument) {
// Try creating an empty document with busy state. Readonly is
// set automatically.
CountedBrowserAccessibility::reset();
- const int32 busy_state = 1 << AccessibilityNodeData::STATE_BUSY;
- const int32 readonly_state = 1 << AccessibilityNodeData::STATE_READONLY;
+ const int32 busy_state = 1 << WebKit::WebAXStateBusy;
+ const int32 readonly_state = 1 << WebKit::WebAXStateReadonly;
+ const int32 enabled_state = 1 << WebKit::WebAXStateEnabled;
scoped_ptr<BrowserAccessibilityManager> manager(
new BrowserAccessibilityManagerWin(
GetDesktopWindow(),
@@ -592,28 +615,28 @@ 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(AccessibilityNodeData::ROLE_ROOT_WEB_AREA, root->role());
- EXPECT_EQ(busy_state | readonly_state, root->state());
+ EXPECT_EQ(WebKit::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 = AccessibilityNodeData::ROLE_ROOT_WEB_AREA;
+ tree1_1.role = WebKit::WebAXRoleRootWebArea;
tree1_1.child_ids.push_back(2);
AccessibilityNodeData tree1_2;
tree1_2.id = 2;
- tree1_2.role = AccessibilityNodeData::ROLE_TEXT_FIELD;
+ tree1_2.role = WebKit::WebAXRoleTextField;
// Process a load complete.
- std::vector<AccessibilityHostMsg_NotificationParams> params;
- params.push_back(AccessibilityHostMsg_NotificationParams());
- AccessibilityHostMsg_NotificationParams* msg = &params[0];
- msg->notification_type = AccessibilityNotificationLoadComplete;
+ std::vector<AccessibilityHostMsg_EventParams> params;
+ params.push_back(AccessibilityHostMsg_EventParams());
+ AccessibilityHostMsg_EventParams* msg = &params[0];
+ msg->event_type = WebKit::WebAXEventLoadComplete;
msg->nodes.push_back(tree1_1);
msg->nodes.push_back(tree1_2);
msg->id = tree1_1.id;
- manager->OnAccessibilityNotifications(params);
+ manager->OnAccessibilityEvents(params);
// Save for later comparison.
BrowserAccessibility* acc1_2 = manager->GetFromRendererID(2);
@@ -622,18 +645,18 @@ TEST_F(BrowserAccessibilityTest, TestCreateEmptyDocument) {
EXPECT_NE(root, manager->GetRoot());
// And the proper child remains.
- EXPECT_EQ(AccessibilityNodeData::ROLE_TEXT_FIELD, acc1_2->role());
+ EXPECT_EQ(WebKit::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 = AccessibilityNodeData::ROLE_ROOT_WEB_AREA;
+ tree2_1.role = WebKit::WebAXRoleRootWebArea;
tree2_1.child_ids.push_back(3);
AccessibilityNodeData tree2_2;
tree2_2.id = 3;
- tree2_2.role = AccessibilityNodeData::ROLE_BUTTON;
+ tree2_2.role = WebKit::WebAXRoleButton;
msg->nodes.clear();
msg->nodes.push_back(tree2_1);
@@ -641,7 +664,7 @@ TEST_F(BrowserAccessibilityTest, TestCreateEmptyDocument) {
msg->id = tree2_1.id;
// Fire another load complete.
- manager->OnAccessibilityNotifications(params);
+ manager->OnAccessibilityEvents(params);
BrowserAccessibility* acc2_2 = manager->GetFromRendererID(3);
@@ -649,7 +672,7 @@ TEST_F(BrowserAccessibilityTest, TestCreateEmptyDocument) {
EXPECT_NE(root, manager->GetRoot());
// And the new child exists.
- EXPECT_EQ(AccessibilityNodeData::ROLE_BUTTON, acc2_2->role());
+ EXPECT_EQ(WebKit::WebAXRoleButton, acc2_2->role());
EXPECT_EQ(3, acc2_2->renderer_id());
// Ensure we properly cleaned up.
diff --git a/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc b/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
index 5e3effe3c2a..eb61a1c8d24 100644
--- a/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
+++ b/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
@@ -10,7 +10,7 @@
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_widget_host_view.h"
-#include "content/shell/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/accessibility_browser_test_utils.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
@@ -40,7 +40,7 @@ class CrossPlatformAccessibilityBrowserTest : public ContentBrowserTest {
const AccessibilityNodeDataTreeNode& GetAccessibilityNodeDataTree(
AccessibilityMode accessibility_mode = AccessibilityModeComplete) {
AccessibilityNotificationWaiter waiter(
- shell(), accessibility_mode, AccessibilityNotificationLayoutComplete);
+ shell(), accessibility_mode, WebKit::WebAXEventLayoutComplete);
waiter.WaitForNotification();
return waiter.GetAccessibilityNodeDataTree();
}
@@ -89,16 +89,15 @@ CrossPlatformAccessibilityBrowserTest::TearDownInProcessBrowserTestFixture() {
}
// Convenience method to get the value of a particular AccessibilityNodeData
-// node attribute as a UTF-8 const char*.
+// node attribute as a UTF-8 string.
std::string CrossPlatformAccessibilityBrowserTest::GetAttr(
const AccessibilityNodeData& node,
const AccessibilityNodeData::StringAttribute attr) {
- std::map<AccessibilityNodeData::StringAttribute, string16>::const_iterator
- iter = node.string_attributes.find(attr);
- if (iter != node.string_attributes.end())
- return UTF16ToUTF8(iter->second);
- else
- return std::string();
+ for (size_t i = 0; i < node.string_attributes.size(); ++i) {
+ if (node.string_attributes[i].first == attr)
+ return node.string_attributes[i].second;
+ }
+ return std::string();
}
// Convenience method to get the value of a particular AccessibilityNodeData
@@ -106,12 +105,11 @@ std::string CrossPlatformAccessibilityBrowserTest::GetAttr(
int CrossPlatformAccessibilityBrowserTest::GetIntAttr(
const AccessibilityNodeData& node,
const AccessibilityNodeData::IntAttribute attr) {
- std::map<AccessibilityNodeData::IntAttribute, int32>::const_iterator iter =
- node.int_attributes.find(attr);
- if (iter != node.int_attributes.end())
- return iter->second;
- else
- return -1;
+ for (size_t i = 0; i < node.int_attributes.size(); ++i) {
+ if (node.int_attributes[i].first == attr)
+ return node.int_attributes[i].second;
+ }
+ return -1;
}
// Convenience method to get the value of a particular AccessibilityNodeData
@@ -119,12 +117,11 @@ int CrossPlatformAccessibilityBrowserTest::GetIntAttr(
bool CrossPlatformAccessibilityBrowserTest::GetBoolAttr(
const AccessibilityNodeData& node,
const AccessibilityNodeData::BoolAttribute attr) {
- std::map<AccessibilityNodeData::BoolAttribute, bool>::const_iterator iter =
- node.bool_attributes.find(attr);
- if (iter != node.bool_attributes.end())
- return iter->second;
- else
- return false;
+ for (size_t i = 0; i < node.bool_attributes.size(); ++i) {
+ if (node.bool_attributes[i].first == attr)
+ return node.bool_attributes[i].second;
+ }
+ return false;
}
// Marked flaky per http://crbug.com/101984
@@ -152,13 +149,15 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
EXPECT_STREQ(
"text/html",
GetAttr(tree, AccessibilityNodeData::ATTR_DOC_MIMETYPE).c_str());
- EXPECT_STREQ("Accessibility Test", UTF16ToUTF8(tree.name).c_str());
- EXPECT_EQ(AccessibilityNodeData::ROLE_ROOT_WEB_AREA, tree.role);
+ EXPECT_STREQ(
+ "Accessibility Test",
+ GetAttr(tree, AccessibilityNodeData::ATTR_NAME).c_str());
+ EXPECT_EQ(WebKit::WebAXRoleRootWebArea, tree.role);
// Check properites of the BODY element.
ASSERT_EQ(1U, tree.children.size());
const AccessibilityNodeDataTreeNode& body = tree.children[0];
- EXPECT_EQ(AccessibilityNodeData::ROLE_GROUP, body.role);
+ EXPECT_EQ(WebKit::WebAXRoleGroup, body.role);
EXPECT_STREQ("body",
GetAttr(body, AccessibilityNodeData::ATTR_HTML_TAG).c_str());
EXPECT_STREQ("block",
@@ -168,31 +167,31 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
ASSERT_EQ(2U, body.children.size());
const AccessibilityNodeDataTreeNode& button = body.children[0];
- EXPECT_EQ(AccessibilityNodeData::ROLE_BUTTON, button.role);
+ EXPECT_EQ(WebKit::WebAXRoleButton, button.role);
EXPECT_STREQ(
"input", GetAttr(button, AccessibilityNodeData::ATTR_HTML_TAG).c_str());
- EXPECT_STREQ("push", UTF16ToUTF8(button.name).c_str());
+ EXPECT_STREQ(
+ "push",
+ GetAttr(button, AccessibilityNodeData::ATTR_NAME).c_str());
EXPECT_STREQ(
"inline-block",
GetAttr(button, AccessibilityNodeData::ATTR_DISPLAY).c_str());
ASSERT_EQ(2U, button.html_attributes.size());
- EXPECT_STREQ("type", UTF16ToUTF8(button.html_attributes[0].first).c_str());
- EXPECT_STREQ("button", UTF16ToUTF8(button.html_attributes[0].second).c_str());
- EXPECT_STREQ("value", UTF16ToUTF8(button.html_attributes[1].first).c_str());
- EXPECT_STREQ("push", UTF16ToUTF8(button.html_attributes[1].second).c_str());
+ EXPECT_STREQ("type", button.html_attributes[0].first.c_str());
+ EXPECT_STREQ("button", button.html_attributes[0].second.c_str());
+ EXPECT_STREQ("value", button.html_attributes[1].first.c_str());
+ EXPECT_STREQ("push", button.html_attributes[1].second.c_str());
const AccessibilityNodeDataTreeNode& checkbox = body.children[1];
- EXPECT_EQ(AccessibilityNodeData::ROLE_CHECKBOX, checkbox.role);
+ EXPECT_EQ(WebKit::WebAXRoleCheckBox, checkbox.role);
EXPECT_STREQ(
"input", GetAttr(checkbox, AccessibilityNodeData::ATTR_HTML_TAG).c_str());
EXPECT_STREQ(
"inline-block",
GetAttr(checkbox, AccessibilityNodeData::ATTR_DISPLAY).c_str());
ASSERT_EQ(1U, checkbox.html_attributes.size());
- EXPECT_STREQ(
- "type", UTF16ToUTF8(checkbox.html_attributes[0].first).c_str());
- EXPECT_STREQ(
- "checkbox", UTF16ToUTF8(checkbox.html_attributes[0].second).c_str());
+ EXPECT_STREQ("type", checkbox.html_attributes[0].first.c_str());
+ EXPECT_STREQ("checkbox", checkbox.html_attributes[0].second.c_str());
}
IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
@@ -212,12 +211,14 @@ 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(AccessibilityNodeData::ROLE_TEXT_FIELD, text.role);
+ EXPECT_EQ(WebKit::WebAXRoleTextField, text.role);
EXPECT_STREQ(
"input", GetAttr(text, AccessibilityNodeData::ATTR_HTML_TAG).c_str());
EXPECT_EQ(0, GetIntAttr(text, AccessibilityNodeData::ATTR_TEXT_SEL_START));
EXPECT_EQ(0, GetIntAttr(text, AccessibilityNodeData::ATTR_TEXT_SEL_END));
- EXPECT_STREQ("Hello, world.", UTF16ToUTF8(text.value).c_str());
+ EXPECT_STREQ(
+ "Hello, world.",
+ GetAttr(text, AccessibilityNodeData::ATTR_VALUE).c_str());
// TODO(dmazzoni): as soon as more accessibility code is cross-platform,
// this code should test that the accessible info is dynamically updated
@@ -241,12 +242,14 @@ 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(AccessibilityNodeData::ROLE_TEXT_FIELD, text.role);
+ EXPECT_EQ(WebKit::WebAXRoleTextField, text.role);
EXPECT_STREQ(
"input", GetAttr(text, AccessibilityNodeData::ATTR_HTML_TAG).c_str());
EXPECT_EQ(0, GetIntAttr(text, AccessibilityNodeData::ATTR_TEXT_SEL_START));
EXPECT_EQ(13, GetIntAttr(text, AccessibilityNodeData::ATTR_TEXT_SEL_END));
- EXPECT_STREQ("Hello, world.", UTF16ToUTF8(text.value).c_str());
+ EXPECT_STREQ(
+ "Hello, world.",
+ GetAttr(text, AccessibilityNodeData::ATTR_VALUE).c_str());
}
IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
@@ -266,23 +269,32 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
const AccessibilityNodeDataTreeNode& tree = GetAccessibilityNodeDataTree();
ASSERT_EQ(1U, tree.children.size());
const AccessibilityNodeDataTreeNode& table = tree.children[0];
- EXPECT_EQ(AccessibilityNodeData::ROLE_TABLE, table.role);
+ EXPECT_EQ(WebKit::WebAXRoleTable, table.role);
const AccessibilityNodeDataTreeNode& row = table.children[0];
- EXPECT_EQ(AccessibilityNodeData::ROLE_ROW, row.role);
+ EXPECT_EQ(WebKit::WebAXRoleRow, row.role);
const AccessibilityNodeDataTreeNode& cell1 = row.children[0];
- EXPECT_EQ(AccessibilityNodeData::ROLE_CELL, cell1.role);
+ EXPECT_EQ(WebKit::WebAXRoleCell, cell1.role);
const AccessibilityNodeDataTreeNode& cell2 = row.children[1];
- EXPECT_EQ(AccessibilityNodeData::ROLE_CELL, cell2.role);
+ EXPECT_EQ(WebKit::WebAXRoleCell, cell2.role);
const AccessibilityNodeDataTreeNode& column1 = table.children[1];
- EXPECT_EQ(AccessibilityNodeData::ROLE_COLUMN, column1.role);
+ EXPECT_EQ(WebKit::WebAXRoleColumn, column1.role);
EXPECT_EQ(0U, column1.children.size());
- EXPECT_EQ(1U, column1.indirect_child_ids.size());
- EXPECT_EQ(cell1.id, column1.indirect_child_ids[0]);
+ EXPECT_EQ(1U, column1.intlist_attributes.size());
+ EXPECT_EQ(AccessibilityNodeData::ATTR_INDIRECT_CHILD_IDS,
+ column1.intlist_attributes[0].first);
+ const std::vector<int32> column1_indirect_child_ids =
+ column1.intlist_attributes[0].second;
+ 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(AccessibilityNodeData::ROLE_COLUMN, column2.role);
+ EXPECT_EQ(WebKit::WebAXRoleColumn, column2.role);
EXPECT_EQ(0U, column2.children.size());
- EXPECT_EQ(1U, column2.indirect_child_ids.size());
- EXPECT_EQ(cell2.id, column2.indirect_child_ids[0]);
+ EXPECT_EQ(AccessibilityNodeData::ATTR_INDIRECT_CHILD_IDS,
+ column2.intlist_attributes[0].first);
+ const std::vector<int32> column2_indirect_child_ids =
+ column2.intlist_attributes[0].second;
+ EXPECT_EQ(1U, column2_indirect_child_ids.size());
+ EXPECT_EQ(cell2.id, column2_indirect_child_ids[0]);
}
IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
@@ -328,8 +340,10 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
ASSERT_EQ(3U, body.children.size());
const AccessibilityNodeDataTreeNode& button1 = body.children[0];
- EXPECT_EQ(AccessibilityNodeData::ROLE_BUTTON, button1.role);
- EXPECT_STREQ("Button 1", UTF16ToUTF8(button1.name).c_str());
+ EXPECT_EQ(WebKit::WebAXRoleButton, button1.role);
+ EXPECT_STREQ(
+ "Button 1",
+ GetAttr(button1, AccessibilityNodeData::ATTR_NAME).c_str());
const AccessibilityNodeDataTreeNode& iframe = body.children[1];
EXPECT_STREQ("iframe",
@@ -337,23 +351,25 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
ASSERT_EQ(1U, iframe.children.size());
const AccessibilityNodeDataTreeNode& scroll_area = iframe.children[0];
- EXPECT_EQ(AccessibilityNodeData::ROLE_SCROLLAREA, scroll_area.role);
+ EXPECT_EQ(WebKit::WebAXRoleScrollArea, scroll_area.role);
ASSERT_EQ(1U, scroll_area.children.size());
const AccessibilityNodeDataTreeNode& sub_document = scroll_area.children[0];
- EXPECT_EQ(AccessibilityNodeData::ROLE_WEB_AREA, sub_document.role);
+ EXPECT_EQ(WebKit::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(AccessibilityNodeData::ROLE_BUTTON, button2.role);
- EXPECT_STREQ("Button 2", UTF16ToUTF8(button2.name).c_str());
+ EXPECT_EQ(WebKit::WebAXRoleButton, button2.role);
+ EXPECT_STREQ("Button 2",
+ GetAttr(button2, AccessibilityNodeData::ATTR_NAME).c_str());
const AccessibilityNodeDataTreeNode& button3 = body.children[2];
- EXPECT_EQ(AccessibilityNodeData::ROLE_BUTTON, button3.role);
- EXPECT_STREQ("Button 3", UTF16ToUTF8(button3.name).c_str());
+ EXPECT_EQ(WebKit::WebAXRoleButton, button3.role);
+ EXPECT_STREQ("Button 3",
+ GetAttr(button3, AccessibilityNodeData::ATTR_NAME).c_str());
}
IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
@@ -397,13 +413,13 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
const AccessibilityNodeDataTreeNode& tree = GetAccessibilityNodeDataTree();
const AccessibilityNodeDataTreeNode& table = tree.children[0];
- EXPECT_EQ(AccessibilityNodeData::ROLE_TABLE, table.role);
+ EXPECT_EQ(WebKit::WebAXRoleTable, table.role);
ASSERT_GE(table.children.size(), 5U);
- EXPECT_EQ(AccessibilityNodeData::ROLE_ROW, table.children[0].role);
- EXPECT_EQ(AccessibilityNodeData::ROLE_ROW, table.children[1].role);
- EXPECT_EQ(AccessibilityNodeData::ROLE_COLUMN, table.children[2].role);
- EXPECT_EQ(AccessibilityNodeData::ROLE_COLUMN, table.children[3].role);
- EXPECT_EQ(AccessibilityNodeData::ROLE_COLUMN, table.children[4].role);
+ 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(3,
GetIntAttr(table, AccessibilityNodeData::ATTR_TABLE_COLUMN_COUNT));
EXPECT_EQ(2, GetIntAttr(table, AccessibilityNodeData::ATTR_TABLE_ROW_COUNT));
@@ -413,13 +429,17 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
const AccessibilityNodeDataTreeNode& cell3 = table.children[1].children[0];
const AccessibilityNodeDataTreeNode& cell4 = table.children[1].children[1];
- ASSERT_EQ(6U, table.cell_ids.size());
- EXPECT_EQ(cell1.id, table.cell_ids[0]);
- EXPECT_EQ(cell1.id, table.cell_ids[1]);
- EXPECT_EQ(cell2.id, table.cell_ids[2]);
- EXPECT_EQ(cell3.id, table.cell_ids[3]);
- EXPECT_EQ(cell4.id, table.cell_ids[4]);
- EXPECT_EQ(cell4.id, table.cell_ids[5]);
+ ASSERT_EQ(AccessibilityNodeData::ATTR_CELL_IDS,
+ table.intlist_attributes[0].first);
+ const std::vector<int32>& table_cell_ids =
+ table.intlist_attributes[0].second;
+ ASSERT_EQ(6U, table_cell_ids.size());
+ EXPECT_EQ(cell1.id, table_cell_ids[0]);
+ EXPECT_EQ(cell1.id, table_cell_ids[1]);
+ EXPECT_EQ(cell2.id, table_cell_ids[2]);
+ EXPECT_EQ(cell3.id, table_cell_ids[3]);
+ EXPECT_EQ(cell4.id, table_cell_ids[4]);
+ EXPECT_EQ(cell4.id, table_cell_ids[5]);
EXPECT_EQ(0, GetIntAttr(cell1,
AccessibilityNodeData::ATTR_TABLE_CELL_COLUMN_INDEX));
diff --git a/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index d0ff119fd24..948b8fde628 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -21,7 +21,7 @@
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/url_constants.h"
-#include "content/shell/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/accessibility_browser_test_utils.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
@@ -140,14 +140,14 @@ void DumpAccessibilityTreeTest::RunTest(
printf("Testing: %s\n", html_file.MaybeAsASCII().c_str());
std::string html_contents;
- file_util::ReadFileToString(html_file, &html_contents);
+ base::ReadFileToString(html_file, &html_contents);
// Read the expected file.
std::string expected_contents_raw;
base::FilePath expected_file =
base::FilePath(html_file.RemoveExtension().value() +
AccessibilityTreeFormatter::GetExpectedFileSuffix());
- file_util::ReadFileToString(expected_file, &expected_contents_raw);
+ base::ReadFileToString(expected_file, &expected_contents_raw);
// 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.
@@ -166,7 +166,7 @@ void DumpAccessibilityTreeTest::RunTest(
html_file.BaseName().MaybeAsASCII().c_str());
AccessibilityNotificationWaiter waiter(
shell(), AccessibilityModeComplete,
- AccessibilityNotificationLoadComplete);
+ WebKit::WebAXEventLoadComplete);
NavigateToURL(shell(), url);
waiter.WaitForNotification();
diff --git a/chromium/content/browser/android/OWNERS b/chromium/content/browser/android/OWNERS
index 6084aca7150..a5cf4a90179 100644
--- a/chromium/content/browser/android/OWNERS
+++ b/chromium/content/browser/android/OWNERS
@@ -3,6 +3,3 @@ joth@chromium.org
tedchoc@chromium.org
yfriedman@chromium.org
sievers@chromium.org
-
-# per-file rules:
-per-file *media*=qinmin@chromium.org
diff --git a/chromium/content/browser/android/android_browser_process.cc b/chromium/content/browser/android/android_browser_process.cc
deleted file mode 100644
index edc48e62619..00000000000
--- a/chromium/content/browser/android/android_browser_process.cc
+++ /dev/null
@@ -1,47 +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/android_browser_process.h"
-
-#include "base/android/jni_string.h"
-#include "base/debug/debugger.h"
-#include "base/logging.h"
-#include "content/browser/android/content_startup_flags.h"
-#include "content/public/common/content_constants.h"
-#include "jni/AndroidBrowserProcess_jni.h"
-
-using base::android::ConvertJavaStringToUTF8;
-
-namespace content {
-
-static void SetCommandLineFlags(JNIEnv*env,
- jclass clazz,
- jint max_render_process_count,
- jstring plugin_descriptor) {
- std::string plugin_str = (plugin_descriptor == NULL ?
- std::string() : ConvertJavaStringToUTF8(env, plugin_descriptor));
- SetContentCommandLineFlags(max_render_process_count, plugin_str);
-}
-
-static jboolean IsOfficialBuild(JNIEnv* env, jclass clazz) {
-#if defined(OFFICIAL_BUILD)
- return true;
-#else
- return false;
-#endif
-}
-
-static jboolean IsPluginEnabled(JNIEnv* env, jclass clazz) {
-#if defined(ENABLE_PLUGINS)
- return true;
-#else
- return false;
-#endif
-}
-
-bool RegisterAndroidBrowserProcess(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
-} // namespace
diff --git a/chromium/content/browser/android/android_browser_process.h b/chromium/content/browser/android/android_browser_process.h
deleted file mode 100644
index fbd06e822b7..00000000000
--- a/chromium/content/browser/android/android_browser_process.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_APP_ANDROID_ANDROID_BROWSER_PROCESS_H_
-#define CONTENT_APP_ANDROID_ANDROID_BROWSER_PROCESS_H_
-
-#include <jni.h>
-
-namespace content {
-
-bool RegisterAndroidBrowserProcess(JNIEnv* env);
-
-} // namespace content
-
-#endif // CONTENT_APP_ANDROID_ANDROID_BROWSER_PROCESS_H_
diff --git a/chromium/content/browser/android/browser_jni_registrar.cc b/chromium/content/browser/android/browser_jni_registrar.cc
deleted file mode 100644
index 35da3af3f3f..00000000000
--- a/chromium/content/browser/android/browser_jni_registrar.cc
+++ /dev/null
@@ -1,83 +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/browser_jni_registrar.h"
-
-#include "base/android/jni_android.h"
-#include "base/android/jni_registrar.h"
-#include "content/browser/accessibility/browser_accessibility_android.h"
-#include "content/browser/accessibility/browser_accessibility_manager_android.h"
-#include "content/browser/android/android_browser_process.h"
-#include "content/browser/android/browser_startup_config.h"
-#include "content/browser/android/child_process_launcher_android.h"
-#include "content/browser/android/content_settings.h"
-#include "content/browser/android/content_video_view.h"
-#include "content/browser/android/content_view_core_impl.h"
-#include "content/browser/android/content_view_render_view.h"
-#include "content/browser/android/content_view_statics.h"
-#include "content/browser/android/date_time_chooser_android.h"
-#include "content/browser/android/download_controller_android_impl.h"
-#include "content/browser/android/interstitial_page_delegate_android.h"
-#include "content/browser/android/load_url_params.h"
-#include "content/browser/android/media_resource_getter_impl.h"
-#include "content/browser/android/surface_texture_peer_browser_impl.h"
-#include "content/browser/android/touch_point.h"
-#include "content/browser/android/tracing_intent_handler.h"
-#include "content/browser/android/vibration_message_filter.h"
-#include "content/browser/android/web_contents_observer_android.h"
-#include "content/browser/device_orientation/data_fetcher_impl_android.h"
-#include "content/browser/geolocation/location_api_adapter_android.h"
-#include "content/browser/power_save_blocker_android.h"
-#include "content/browser/renderer_host/ime_adapter_android.h"
-#include "content/browser/renderer_host/java/java_bound_object.h"
-#include "content/browser/speech/speech_recognizer_impl_android.h"
-
-using content::SurfaceTexturePeerBrowserImpl;
-
-namespace {
-base::android::RegistrationMethod kContentRegisteredMethods[] = {
- {"AndroidLocationApiAdapter",
- content::AndroidLocationApiAdapter::RegisterGeolocationService},
- {"AndroidBrowserProcess", content::RegisterAndroidBrowserProcess},
- {"BrowserAccessibilityManager",
- content::RegisterBrowserAccessibilityManager},
- {"BrowserStartupConfiguration", content::RegisterBrowserStartupConfig},
- {"ChildProcessLauncher", content::RegisterChildProcessLauncher},
- {"ContentSettings", content::ContentSettings::RegisterContentSettings},
- {"ContentViewRenderView",
- content::ContentViewRenderView::RegisterContentViewRenderView},
- {"ContentVideoView", content::ContentVideoView::RegisterContentVideoView},
- {"ContentViewCore", content::RegisterContentViewCore},
- {"DataFetcherImplAndroid", content::DataFetcherImplAndroid::Register},
- {"DateTimePickerAndroid", content::RegisterDateTimeChooserAndroid},
- {"DownloadControllerAndroidImpl",
- content::DownloadControllerAndroidImpl::RegisterDownloadController},
- {"InterstitialPageDelegateAndroid",
- content::InterstitialPageDelegateAndroid::
- RegisterInterstitialPageDelegateAndroid},
- {"MediaResourceGetterImpl",
- content::MediaResourceGetterImpl::RegisterMediaResourceGetter},
- {"LoadUrlParams", content::RegisterLoadUrlParams},
- {"PowerSaveBlock", content::RegisterPowerSaveBlocker},
- {"RegisterImeAdapter", content::RegisterImeAdapter},
- {"SpeechRecognizerImplAndroid",
- content::SpeechRecognizerImplAndroid::RegisterSpeechRecognizer},
- {"TouchPoint", content::RegisterTouchPoint},
- {"TracingIntentHandler", content::RegisterTracingIntentHandler},
- {"VibrationMessageFilter", content::VibrationMessageFilter::Register},
- {"WebContentsObserverAndroid", content::RegisterWebContentsObserverAndroid},
- {"WebViewStatics", content::RegisterWebViewStatics}, };
-
-} // namespace
-
-namespace content {
-namespace android {
-
-bool RegisterBrowserJni(JNIEnv* env) {
- return RegisterNativeMethods(env, kContentRegisteredMethods,
- arraysize(kContentRegisteredMethods));
-}
-
-} // namespace android
-} // namespace content
diff --git a/chromium/content/browser/android/browser_jni_registrar.h b/chromium/content/browser/android/browser_jni_registrar.h
deleted file mode 100644
index 15f4fb34e10..00000000000
--- a/chromium/content/browser/android/browser_jni_registrar.h
+++ /dev/null
@@ -1,21 +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_BROWSER_JNI_REGISTRAR_H_
-#define CONTENT_BROWSER_ANDROID_BROWSER_JNI_REGISTRAR_H_
-
-#include <jni.h>
-
-#include "content/common/content_export.h"
-
-namespace content {
-namespace android {
-
-// Register all JNI bindings necessary for content browser.
-CONTENT_EXPORT bool RegisterBrowserJni(JNIEnv* env);
-
-} // namespace android
-} // namespace content
-
-#endif // CONTENT_BROWSER_ANDROID_BROWSER_JNI_REGISTRAR_H_
diff --git a/chromium/content/browser/android/browser_startup_config.cc b/chromium/content/browser/android/browser_startup_config.cc
deleted file mode 100644
index 3e742080695..00000000000
--- a/chromium/content/browser/android/browser_startup_config.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/android/browser_startup_config.h"
-
-#include "base/android/jni_android.h"
-#include "jni/BrowserStartupConfig_jni.h"
-
-namespace content {
-
-bool BrowserMayStartAsynchronously() {
- JNIEnv* env = base::android::AttachCurrentThread();
- return Java_BrowserStartupConfig_browserMayStartAsynchonously(env);
-}
-
-void BrowserStartupComplete(int result) {
- JNIEnv* env = base::android::AttachCurrentThread();
- Java_BrowserStartupConfig_browserStartupComplete(env, result);
-}
-
-bool RegisterBrowserStartupConfig(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-} // namespace content
diff --git a/chromium/content/browser/android/browser_startup_controller.cc b/chromium/content/browser/android/browser_startup_controller.cc
new file mode 100644
index 00000000000..502f198edba
--- /dev/null
+++ b/chromium/content/browser/android/browser_startup_controller.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/android/browser_startup_controller.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "content/browser/android/content_startup_flags.h"
+
+#include "jni/BrowserStartupController_jni.h"
+
+namespace content {
+
+bool BrowserMayStartAsynchronously() {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ return Java_BrowserStartupController_browserMayStartAsynchonously(env);
+}
+
+void BrowserStartupComplete(int result) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_BrowserStartupController_browserStartupComplete(env, result);
+}
+
+bool RegisterBrowserStartupController(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+static void SetCommandLineFlags(JNIEnv* env,
+ jclass clazz,
+ jint max_render_process_count,
+ jstring plugin_descriptor) {
+ std::string plugin_str =
+ (plugin_descriptor == NULL
+ ? std::string()
+ : base::android::ConvertJavaStringToUTF8(env, plugin_descriptor));
+ SetContentCommandLineFlags(max_render_process_count, plugin_str);
+}
+
+static jboolean IsOfficialBuild(JNIEnv* env, jclass clazz) {
+#if defined(OFFICIAL_BUILD)
+ return true;
+#else
+ return false;
+#endif
+}
+
+static jboolean IsPluginEnabled(JNIEnv* env, jclass clazz) {
+#if defined(ENABLE_PLUGINS)
+ return true;
+#else
+ return false;
+#endif
+}
+
+} // namespace content
diff --git a/chromium/content/browser/android/browser_startup_config.h b/chromium/content/browser/android/browser_startup_controller.h
index 95575f2bc2d..6fa334e8f3a 100644
--- a/chromium/content/browser/android/browser_startup_config.h
+++ b/chromium/content/browser/android/browser_startup_controller.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_BROWSER_STARTUP_CONFIGURATION_H_
-#define CONTENT_BROWSER_BROWSER_STARTUP_CONFIGURATION_H_
+#ifndef CONTENT_BROWSER_BROWSER_STARTUP_CONTROLLER_H_
+#define CONTENT_BROWSER_BROWSER_STARTUP_CONTROLLER_H_
#include <jni.h>
@@ -12,7 +12,7 @@ namespace content {
bool BrowserMayStartAsynchronously();
void BrowserStartupComplete(int result);
-bool RegisterBrowserStartupConfig(JNIEnv* env);
+bool RegisterBrowserStartupController(JNIEnv* env);
} // namespace content
-#endif // CONTENT_BROWSER_BROWSER_STARTUP_CONFIGURATION_H_
+#endif // CONTENT_BROWSER_BROWSER_STARTUP_CONTROLLER_H_
diff --git a/chromium/content/browser/android/child_process_launcher_android.cc b/chromium/content/browser/android/child_process_launcher_android.cc
index d73e2992112..962fee861f7 100644
--- a/chromium/content/browser/android/child_process_launcher_android.cc
+++ b/chromium/content/browser/android/child_process_launcher_android.cc
@@ -8,6 +8,7 @@
#include "base/android/jni_array.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.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/render_view_host_impl.h"
#include "content/public/browser/browser_thread.h"
@@ -15,7 +16,6 @@
#include "content/public/common/content_switches.h"
#include "jni/ChildProcessLauncher_jni.h"
#include "media/base/android/media_player_android.h"
-#include "media/base/android/media_player_manager.h"
#include "ui/gl/android/scoped_java_surface.h"
using base::android::AttachCurrentThread;
diff --git a/chromium/content/browser/android/content_startup_flags.cc b/chromium/content/browser/android/content_startup_flags.cc
index 065b3e70b3f..b755e4dc783 100644
--- a/chromium/content/browser/android/content_startup_flags.cc
+++ b/chromium/content/browser/android/content_startup_flags.cc
@@ -58,9 +58,12 @@ void SetContentCommandLineFlags(int max_render_process_count,
parsed_command_line->AppendSwitch(
switches::kEnableCompositedScrollingForFrames);
parsed_command_line->AppendSwitch(switches::kEnableBeginFrameScheduling);
+ parsed_command_line->AppendSwitch(switches::kEnableDeadlineScheduling);
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);
// Run the GPU service as a thread in the browser instead of as a
diff --git a/chromium/content/browser/android/content_video_view.cc b/chromium/content/browser/android/content_video_view.cc
index 4a0fdc67a44..b8d5c64d542 100644
--- a/chromium/content/browser/android/content_video_view.cc
+++ b/chromium/content/browser/android/content_video_view.cc
@@ -6,7 +6,7 @@
#include "base/command_line.h"
#include "base/logging.h"
-#include "content/browser/android/browser_media_player_manager.h"
+#include "content/browser/media/android/browser_media_player_manager.h"
#include "content/common/android/surface_texture_peer.h"
#include "content/public/common/content_switches.h"
#include "jni/ContentVideoView_jni.h"
diff --git a/chromium/content/browser/android/content_view_core_impl.cc b/chromium/content/browser/android/content_view_core_impl.cc
index 33b3f068d2a..dd15c1f67b8 100644
--- a/chromium/content/browser/android/content_view_core_impl.cc
+++ b/chromium/content/browser/android/content_view_core_impl.cc
@@ -15,10 +15,10 @@
#include "base/values.h"
#include "cc/layers/layer.h"
#include "cc/output/begin_frame_args.h"
-#include "content/browser/android/browser_media_player_manager.h"
#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/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"
#include "content/browser/renderer_host/java/java_bound_object.h"
@@ -260,6 +260,7 @@ void ContentViewCoreImpl::Observe(int type,
env, obj.obj(), old_pid, new_pid);
}
}
+ SetFocusInternal(HasFocus());
break;
}
case NOTIFICATION_RENDERER_PROCESS_CREATED: {
@@ -341,6 +342,13 @@ void ContentViewCoreImpl::Show() {
void ContentViewCoreImpl::Hide() {
GetWebContents()->WasHidden();
+ PauseVideo();
+}
+
+void ContentViewCoreImpl::PauseVideo() {
+ RenderViewHost* host = web_contents_->GetRenderViewHost();
+ if (host)
+ host->Send(new ViewMsg_PauseVideo(host->GetRoutingID()));
}
void ContentViewCoreImpl::OnTabCrashed() {
@@ -375,6 +383,10 @@ 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())
@@ -577,15 +589,28 @@ void ContentViewCoreImpl::ShowDisambiguationPopup(
java_bitmap.obj());
}
-ScopedJavaLocalRef<jobject> ContentViewCoreImpl::CreateSmoothScroller(
- bool scroll_down, int mouse_event_x, int mouse_event_y) {
+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_createSmoothScroller(
- env, obj.obj(), scroll_down, mouse_event_x, mouse_event_y);
+ 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) {
+ 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);
}
void ContentViewCoreImpl::NotifyExternalSurface(
@@ -817,6 +842,10 @@ WebContents* ContentViewCoreImpl::GetWebContents() const {
}
void ContentViewCoreImpl::SetFocus(JNIEnv* env, jobject obj, jboolean focused) {
+ SetFocusInternal(focused);
+}
+
+void ContentViewCoreImpl::SetFocusInternal(bool focused) {
if (!GetRenderWidgetHostViewAndroid())
return;
@@ -947,20 +976,13 @@ void ContentViewCoreImpl::ScrollEnd(JNIEnv* env, jobject obj, jlong time_ms) {
}
void ContentViewCoreImpl::ScrollBy(JNIEnv* env, jobject obj, jlong time_ms,
- jfloat x, jfloat y, jfloat dx, jfloat dy,
- jboolean last_input_event_for_vsync) {
+ jfloat x, jfloat y, jfloat dx, jfloat dy) {
WebGestureEvent event = MakeGestureEvent(
WebInputEvent::GestureScrollUpdate, time_ms, x, y);
event.data.scrollUpdate.deltaX = -dx / GetDpiScale();
event.data.scrollUpdate.deltaY = -dy / GetDpiScale();
SendGestureEvent(event);
-
- // TODO(brianderson): Clean up last_input_event_for_vsync. crbug.com/247043
- if (last_input_event_for_vsync) {
- SendBeginFrame(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(time_ms));
- }
}
void ContentViewCoreImpl::FlingStart(JNIEnv* env, jobject obj, jlong time_ms,
@@ -1083,19 +1105,12 @@ void ContentViewCoreImpl::PinchEnd(JNIEnv* env, jobject obj, jlong time_ms) {
void ContentViewCoreImpl::PinchBy(JNIEnv* env, jobject obj, jlong time_ms,
jfloat anchor_x, jfloat anchor_y,
- jfloat delta,
- jboolean last_input_event_for_vsync) {
+ jfloat delta) {
WebGestureEvent event = MakeGestureEvent(
WebInputEvent::GesturePinchUpdate, time_ms, anchor_x, anchor_y);
event.data.pinchUpdate.scale = delta;
SendGestureEvent(event);
-
- // TODO(brianderson): Clean up last_input_event_for_vsync. crbug.com/247043
- if (last_input_event_for_vsync) {
- SendBeginFrame(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(time_ms));
- }
}
void ContentViewCoreImpl::SelectBetweenCoordinates(JNIEnv* env, jobject obj,
@@ -1151,6 +1166,15 @@ void ContentViewCoreImpl::GoToNavigationIndex(JNIEnv* env,
UpdateTabCrashedFlag();
}
+void ContentViewCoreImpl::LoadIfNecessary(JNIEnv* env, jobject obj) {
+ web_contents_->GetController().LoadIfNecessary();
+ UpdateTabCrashedFlag();
+}
+
+void ContentViewCoreImpl::RequestRestoreLoad(JNIEnv* env, jobject obj) {
+ web_contents_->GetController().SetNeedsReload();
+}
+
void ContentViewCoreImpl::StopLoading(JNIEnv* env, jobject obj) {
web_contents_->Stop();
}
@@ -1296,12 +1320,8 @@ void ContentViewCoreImpl::AttachExternalVideoSurface(JNIEnv* env,
#if defined(GOOGLE_TV)
RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
web_contents_->GetRenderViewHost());
- BrowserMediaPlayerManager* browser_media_player_manager =
- rvhi ? static_cast<BrowserMediaPlayerManager*>(
- rvhi->media_player_manager())
- : NULL;
- if (browser_media_player_manager) {
- browser_media_player_manager->AttachExternalVideoSurface(
+ if (rvhi && rvhi->media_player_manager()) {
+ rvhi->media_player_manager()->AttachExternalVideoSurface(
static_cast<int>(player_id), jsurface);
}
#endif
@@ -1313,12 +1333,8 @@ void ContentViewCoreImpl::DetachExternalVideoSurface(JNIEnv* env,
#if defined(GOOGLE_TV)
RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
web_contents_->GetRenderViewHost());
- BrowserMediaPlayerManager* browser_media_player_manager =
- rvhi ? static_cast<BrowserMediaPlayerManager*>(
- rvhi->media_player_manager())
- : NULL;
- if (browser_media_player_manager) {
- browser_media_player_manager->DetachExternalVideoSurface(
+ if (rvhi && rvhi->media_player_manager()) {
+ rvhi->media_player_manager()->DetachExternalVideoSurface(
static_cast<int>(player_id));
}
#endif
@@ -1332,6 +1348,8 @@ jboolean ContentViewCoreImpl::IsRenderWidgetHostViewReady(JNIEnv* env,
void ContentViewCoreImpl::ExitFullscreen(JNIEnv* env, jobject obj) {
RenderViewHost* host = web_contents_->GetRenderViewHost();
+ if (!host)
+ return;
host->ExitFullscreen();
}
@@ -1341,6 +1359,8 @@ void ContentViewCoreImpl::UpdateTopControlsState(JNIEnv* env,
bool enable_showing,
bool animate) {
RenderViewHost* host = web_contents_->GetRenderViewHost();
+ if (!host)
+ return;
host->Send(new ViewMsg_UpdateTopControlsState(host->GetRoutingID(),
enable_hiding,
enable_showing,
@@ -1574,17 +1594,12 @@ void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv* env, jobject obj,
return;
RenderWidgetHostImpl* host_impl = RenderWidgetHostImpl::From(
host_view->GetRenderWidgetHost());
- BrowserAccessibilityState* accessibility_state =
- BrowserAccessibilityState::GetInstance();
if (enabled) {
- // 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)
+ BrowserAccessibilityState::GetInstance()->EnableAccessibility();
+ if (host_impl)
host_impl->SetAccessibilityMode(AccessibilityModeComplete);
} else {
- accessibility_state->DisableAccessibility();
+ BrowserAccessibilityState::GetInstance()->DisableAccessibility();
if (host_impl)
host_impl->SetAccessibilityMode(AccessibilityModeOff);
}
diff --git a/chromium/content/browser/android/content_view_core_impl.h b/chromium/content/browser/android/content_view_core_impl.h
index f3cf755257a..765f63da983 100644
--- a/chromium/content/browser/android/content_view_core_impl.h
+++ b/chromium/content/browser/android/content_view_core_impl.h
@@ -60,6 +60,7 @@ class ContentViewCoreImpl : public ContentViewCore,
virtual float GetDpiScale() const OVERRIDE;
virtual void RequestContentClipping(const gfx::Rect& clipping,
const gfx::Size& content_size) OVERRIDE;
+ virtual void PauseVideo() OVERRIDE;
// --------------------------------------------------------------------------
// Methods called from Java via JNI
@@ -107,8 +108,7 @@ class ContentViewCoreImpl : public ContentViewCore,
void ScrollBegin(JNIEnv* env, jobject obj, jlong time_ms, jfloat x, jfloat y);
void ScrollEnd(JNIEnv* env, jobject obj, jlong time_ms);
void ScrollBy(JNIEnv* env, jobject obj, jlong time_ms,
- jfloat x, jfloat y, jfloat dx, jfloat dy,
- jboolean last_input_event_for_vsync);
+ jfloat x, jfloat y, jfloat dx, jfloat dy);
void FlingStart(JNIEnv* env, jobject obj, jlong time_ms,
jfloat x, jfloat y, jfloat vx, jfloat vy);
void FlingCancel(JNIEnv* env, jobject obj, jlong time_ms);
@@ -132,8 +132,7 @@ class ContentViewCoreImpl : public ContentViewCore,
void PinchBegin(JNIEnv* env, jobject obj, jlong time_ms, jfloat x, jfloat y);
void PinchEnd(JNIEnv* env, jobject obj, jlong time_ms);
void PinchBy(JNIEnv* env, jobject obj, jlong time_ms,
- jfloat x, jfloat y, jfloat delta,
- jboolean last_input_event_for_vsync);
+ jfloat x, jfloat y, jfloat delta);
void SelectBetweenCoordinates(JNIEnv* env, jobject obj,
jfloat x1, jfloat y1,
jfloat x2, jfloat y2);
@@ -146,6 +145,8 @@ class ContentViewCoreImpl : public ContentViewCore,
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 CancelPendingReload(JNIEnv* env, jobject obj);
@@ -268,10 +269,16 @@ class ContentViewCoreImpl : public ContentViewCore,
void ShowDisambiguationPopup(
const gfx::Rect& target_rect, const SkBitmap& zoomed_bitmap);
- // Creates a java-side smooth scroller. Used by
+ // Creates a java-side touch gesture, e.g. used by
// chrome.gpuBenchmarking.smoothScrollBy.
- base::android::ScopedJavaLocalRef<jobject> CreateSmoothScroller(
- bool scroll_down, int mouse_event_x, int mouse_event_y);
+ 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);
// Notifies the java object about the external surface, requesting for one if
// necessary.
@@ -335,6 +342,9 @@ class ContentViewCoreImpl : public ContentViewCore,
// |tab_crashed_| accordingly.
void UpdateTabCrashedFlag();
+ // Update focus state of the RenderWidgetHostView.
+ void SetFocusInternal(bool focused);
+
// A weak reference to the Java ContentViewCore object.
JavaObjectWeakGlobalRef java_ref_;
diff --git a/chromium/content/browser/android/content_view_render_view.cc b/chromium/content/browser/android/content_view_render_view.cc
index 37a24aa91c8..4faa4df97aa 100644
--- a/chromium/content/browser/android/content_view_render_view.cc
+++ b/chromium/content/browser/android/content_view_render_view.cc
@@ -29,18 +29,18 @@ bool ContentViewRenderView::RegisterContentViewRenderView(JNIEnv* env) {
return RegisterNativesImpl(env);
}
-ContentViewRenderView::ContentViewRenderView()
- : scheduled_composite_(false),
- weak_factory_(this) {
+ContentViewRenderView::ContentViewRenderView(JNIEnv* env, jobject obj)
+ : buffers_swapped_during_composite_(false) {
+ java_obj_.Reset(env, obj);
}
ContentViewRenderView::~ContentViewRenderView() {
}
// static
-jint Init(JNIEnv* env, jclass clazz) {
+static jint Init(JNIEnv* env, jobject obj) {
ContentViewRenderView* content_view_render_view =
- new ContentViewRenderView();
+ new ContentViewRenderView(env, obj);
return reinterpret_cast<jint>(content_view_render_view);
}
@@ -55,6 +55,8 @@ void ContentViewRenderView::SetCurrentContentView(
reinterpret_cast<ContentViewCoreImpl*>(native_content_view);
if (content_view)
compositor_->SetRootLayer(content_view->GetLayer());
+ else
+ compositor_->SetRootLayer(cc::Layer::Create());
}
void ContentViewRenderView::SurfaceCreated(
@@ -72,28 +74,32 @@ void ContentViewRenderView::SurfaceSetSize(
compositor_->SetWindowBounds(gfx::Size(width, height));
}
+jboolean ContentViewRenderView::Composite(JNIEnv* env, jobject obj) {
+ if (!compositor_)
+ return false;
+
+ buffers_swapped_during_composite_ = false;
+ compositor_->Composite();
+ return buffers_swapped_during_composite_;
+}
+
void ContentViewRenderView::ScheduleComposite() {
- if (scheduled_composite_)
- return;
-
- scheduled_composite_ = true;
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&ContentViewRenderView::Composite,
- weak_factory_.GetWeakPtr()));
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_ContentViewRenderView_requestRender(env, java_obj_.obj());
}
-void ContentViewRenderView::InitCompositor() {
- if (!compositor_)
- compositor_.reset(Compositor::Create(this));
+void ContentViewRenderView::OnSwapBuffersPosted() {
+ buffers_swapped_during_composite_ = true;
}
-void ContentViewRenderView::Composite() {
- if (!compositor_)
- return;
+void ContentViewRenderView::OnSwapBuffersCompleted() {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_ContentViewRenderView_onSwapBuffersCompleted(env, java_obj_.obj());
+}
- scheduled_composite_ = false;
- compositor_->Composite();
+void ContentViewRenderView::InitCompositor() {
+ if (!compositor_)
+ compositor_.reset(Compositor::Create(this));
}
} // 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 dbaeccf7514..714f02f7d32 100644
--- a/chromium/content/browser/android/content_view_render_view.h
+++ b/chromium/content/browser/android/content_view_render_view.h
@@ -5,8 +5,7 @@
#ifndef CONTENT_BROWSER_ANDROID_CONTENT_VIEW_RENDER_VIEW_H_
#define CONTENT_BROWSER_ANDROID_CONTENT_VIEW_RENDER_VIEW_H_
-#include <jni.h>
-
+#include "base/android/jni_helper.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
@@ -20,35 +19,31 @@ class ContentViewRenderView : public CompositorClient {
// Registers the JNI methods for ContentViewRender.
static bool RegisterContentViewRenderView(JNIEnv* env);
- ContentViewRenderView();
+ ContentViewRenderView(JNIEnv* env, jobject obj);
- // --------------------------------------------------------------------------
- // Methods called from Java via JNI
- // --------------------------------------------------------------------------
- static jint Init(JNIEnv* env, jclass clazz);
+ // Methods called from Java via JNI -----------------------------------------
void Destroy(JNIEnv* env, jobject obj);
void SetCurrentContentView(JNIEnv* env, jobject obj, int native_content_view);
void SurfaceCreated(JNIEnv* env, jobject obj, jobject jsurface);
void SurfaceDestroyed(JNIEnv* env, jobject obj);
void SurfaceSetSize(JNIEnv* env, jobject obj, jint width, jint height);
+ jboolean Composite(JNIEnv* env, jobject obj);
+
+ // CompositorClient ---------------------------------------------------------
+ virtual void ScheduleComposite() OVERRIDE;
+ virtual void OnSwapBuffersPosted() OVERRIDE;
+ virtual void OnSwapBuffersCompleted() OVERRIDE;
private:
- friend class base::RefCounted<ContentViewRenderView>;
virtual ~ContentViewRenderView();
- // CompositorClient implementation.
- virtual void ScheduleComposite() OVERRIDE;
-
void InitCompositor();
- void Composite();
- scoped_ptr<content::Compositor> compositor_;
- bool scheduled_composite_;
+ bool buffers_swapped_during_composite_;
- base::WeakPtrFactory<ContentViewRenderView> weak_factory_;
+ base::android::ScopedJavaGlobalRef<jobject> java_obj_;
- // Note that this class does not call back to Java and as a result does not
- // have a reference to its Java object.
+ scoped_ptr<content::Compositor> compositor_;
DISALLOW_COPY_AND_ASSIGN(ContentViewRenderView);
};
diff --git a/chromium/content/browser/android/date_time_chooser_android.cc b/chromium/content/browser/android/date_time_chooser_android.cc
index 0c3ba2d7327..7c91ff0977d 100644
--- a/chromium/content/browser/android/date_time_chooser_android.cc
+++ b/chromium/content/browser/android/date_time_chooser_android.cc
@@ -24,7 +24,14 @@ class DateTimeChooserAndroid::DateTimeIPCSender :
explicit DateTimeIPCSender(RenderViewHost* sender);
virtual ~DateTimeIPCSender() {}
void ReplaceDateTime(int dialog_type,
- int year, int month, int day, int hour, int minute, int second, int week);
+ int year,
+ int month,
+ int day,
+ int hour,
+ int minute,
+ int second,
+ int milli,
+ int week);
void CancelDialog();
private:
@@ -36,9 +43,15 @@ DateTimeChooserAndroid::DateTimeIPCSender::DateTimeIPCSender(
: RenderViewHostObserver(sender) {
}
-void DateTimeChooserAndroid::DateTimeIPCSender::ReplaceDateTime(
- int dialog_type,
- int year, int month, int day, int hour, int minute, int second, int week) {
+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;
@@ -46,6 +59,7 @@ void DateTimeChooserAndroid::DateTimeIPCSender::ReplaceDateTime(
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));
@@ -76,30 +90,60 @@ void DateTimeChooserAndroid::InitializeDateInputTypes(
text_input_type_time, text_input_type_week);
}
-void DateTimeChooserAndroid::ReplaceDateTime(
- JNIEnv* env, jobject, int dialog_type,
- int year, int month, int day, int hour, int minute, int second, int week) {
+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, week);
+ dialog_type, year, month, day, hour, minute, second, milli, week);
}
void DateTimeChooserAndroid::CancelDialog(JNIEnv* env, jobject) {
sender_->CancelDialog();
}
-void DateTimeChooserAndroid::ShowDialog(
- ContentViewCore* content, RenderViewHost* sender,
- int type, int year, int month, int day,
- int hour, int minute, int second, int week, double min, double max) {
+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);
JNIEnv* env = AttachCurrentThread();
j_date_time_chooser_.Reset(Java_DateTimeChooserAndroid_createDateTimeChooser(
- env, content->GetJavaObject().obj(),
+ env,
+ content->GetJavaObject().obj(),
reinterpret_cast<intptr_t>(this),
- type, year, month, day, hour, minute, second, week, min, max));
+ type,
+ year,
+ month,
+ day,
+ hour,
+ minute,
+ second,
+ milli,
+ week,
+ min,
+ max,
+ step));
}
// ----------------------------------------------------------------------------
diff --git a/chromium/content/browser/android/date_time_chooser_android.h b/chromium/content/browser/android/date_time_chooser_android.h
index 646ba3c14ea..68cb4560172 100644
--- a/chromium/content/browser/android/date_time_chooser_android.h
+++ b/chromium/content/browser/android/date_time_chooser_android.h
@@ -24,14 +24,31 @@ class DateTimeChooserAndroid {
// DateTimeChooser implementation:
void ShowDialog(ContentViewCore* content,
RenderViewHost* sender,
- int type, int year, int month, int day,
- int hour, int minute, int second, int week,
- double min, double max);
+ int type,
+ int year,
+ int month,
+ int day,
+ int hour,
+ int minute,
+ int second,
+ int milli,
+ int week,
+ 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 week);
+ void ReplaceDateTime(JNIEnv* env,
+ jobject,
+ jint dialog_type,
+ jint year,
+ jint month,
+ jint day,
+ jint hour,
+ jint minute,
+ jint second,
+ jint milli,
+ jint week);
// Closes the dialog without propagating any changes.
void CancelDialog(JNIEnv* env, jobject);
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 5ab105b9a70..b04e85456f1 100644
--- a/chromium/content/browser/android/in_process/synchronous_compositor_impl.cc
+++ b/chromium/content/browser/android/in_process/synchronous_compositor_impl.cc
@@ -16,13 +16,20 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/renderer/android/synchronous_compositor_factory.h"
+#include "content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h"
+#include "gpu/command_buffer/client/gl_in_process_context.h"
+#include "gpu/command_buffer/service/stream_texture_manager_in_process_android.h"
+#include "ui/gl/android/surface_texture.h"
#include "ui/gl/gl_surface.h"
#include "webkit/common/gpu/context_provider_in_process.h"
+#include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
namespace content {
namespace {
+using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl;
+
int GetInProcessRendererId() {
content::RenderProcessHost::iterator it =
content::RenderProcessHost::AllHostsIterator();
@@ -38,9 +45,39 @@ int GetInProcessRendererId() {
return id;
}
+class VideoContextProvider
+ : public StreamTextureFactorySynchronousImpl::ContextProvider {
+ public:
+ VideoContextProvider(
+ const scoped_refptr<cc::ContextProvider>& context_provider,
+ gpu::GLInProcessContext* gl_in_process_context)
+ : context_provider_(context_provider),
+ gl_in_process_context_(gl_in_process_context) {}
+
+ virtual scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture(
+ uint32 stream_id) OVERRIDE {
+ return gl_in_process_context_->GetSurfaceTexture(stream_id);
+ }
+
+ virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE {
+ return context_provider_->Context3d();
+ }
+
+ private:
+ friend class base::RefCountedThreadSafe<VideoContextProvider>;
+ virtual ~VideoContextProvider() {}
+
+ scoped_refptr<cc::ContextProvider> context_provider_;
+ gpu::GLInProcessContext* gl_in_process_context_;
+
+ DISALLOW_COPY_AND_ASSIGN(VideoContextProvider);
+};
+
class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory {
public:
- SynchronousCompositorFactoryImpl() {
+ SynchronousCompositorFactoryImpl()
+ : wrapped_gl_context_for_main_thread_(NULL),
+ num_hardware_compositors_(0) {
SynchronousCompositorFactory::SetInstance(this);
}
@@ -65,15 +102,59 @@ class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory {
return &synchronous_input_event_filter_;
}
+ scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>
+ CreateOffscreenContext() {
+ if (!gfx::GLSurface::InitializeOneOff())
+ return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>();
+
+ const gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;
+
+ WebKit::WebGraphicsContext3D::Attributes attributes;
+ attributes.antialias = false;
+ attributes.shareResources = true;
+ attributes.noAutomaticFlushes = true;
+
+ gpu::GLInProcessContextAttribs in_process_attribs;
+ WebGraphicsContext3DInProcessCommandBufferImpl::ConvertAttributes(
+ attributes, &in_process_attribs);
+ scoped_ptr<gpu::GLInProcessContext> context(
+ gpu::GLInProcessContext::CreateContext(true,
+ NULL,
+ gfx::Size(1, 1),
+ attributes.shareResources,
+ in_process_attribs,
+ gpu_preference));
+
+ wrapped_gl_context_for_main_thread_ = context.get();
+ if (!context.get())
+ return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>();
+
+ return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>(
+ WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext(
+ context.Pass(), attributes));
+ }
+
virtual scoped_refptr<cc::ContextProvider>
GetOffscreenContextProviderForMainThread() OVERRIDE {
- if (!offscreen_context_for_main_thread_.get() ||
- offscreen_context_for_main_thread_->DestroyedOnMainThread()) {
+ // This check only guarantees the main thread context is created after
+ // a compositor did successfully initialize hardware draw in the past.
+ // In particular this does not guarantee that the main thread context
+ // will fail creation when all compositors release hardware draw.
+ bool failed = !CanCreateMainThreadContext();
+ if (!failed &&
+ (!offscreen_context_for_main_thread_.get() ||
+ offscreen_context_for_main_thread_->DestroyedOnMainThread())) {
offscreen_context_for_main_thread_ =
- webkit::gpu::ContextProviderInProcess::Create();
- if (offscreen_context_for_main_thread_.get() &&
- !offscreen_context_for_main_thread_->BindToCurrentThread())
- offscreen_context_for_main_thread_ = NULL;
+ webkit::gpu::ContextProviderInProcess::Create(
+ CreateOffscreenContext(),
+ "Compositor-Offscreen");
+ failed = !offscreen_context_for_main_thread_.get() ||
+ !offscreen_context_for_main_thread_->BindToCurrentThread();
+ }
+
+ if (failed) {
+ offscreen_context_for_main_thread_ = NULL;
+ wrapped_gl_context_for_main_thread_ = NULL;
}
return offscreen_context_for_main_thread_;
}
@@ -86,25 +167,86 @@ class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory {
// any thread and is lightweight.
virtual scoped_refptr<cc::ContextProvider>
GetOffscreenContextProviderForCompositorThread() OVERRIDE {
- base::AutoLock lock(offscreen_context_for_compositor_thread_creation_lock_);
+ base::AutoLock lock(offscreen_context_for_compositor_thread_lock_);
if (!offscreen_context_for_compositor_thread_.get() ||
offscreen_context_for_compositor_thread_->DestroyedOnMainThread()) {
offscreen_context_for_compositor_thread_ =
- webkit::gpu::ContextProviderInProcess::Create();
+ webkit::gpu::ContextProviderInProcess::CreateOffscreen();
}
return offscreen_context_for_compositor_thread_;
}
+ 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>();
+ }
+
+ void CompositorInitializedHardwareDraw(SynchronousCompositorImpl* compositor);
+ void CompositorReleasedHardwareDraw(SynchronousCompositorImpl* compositor);
+
private:
+ void ReleaseGlobalHardwareResources();
+ bool CanCreateMainThreadContext();
+
SynchronousInputEventFilter synchronous_input_event_filter_;
- // Only guards construction of |offscreen_context_for_compositor_thread_|,
- // not usage.
- base::Lock offscreen_context_for_compositor_thread_creation_lock_;
+ // Only guards construction and destruction of
+ // |offscreen_context_for_compositor_thread_|, not usage.
+ base::Lock offscreen_context_for_compositor_thread_lock_;
scoped_refptr<cc::ContextProvider> offscreen_context_for_main_thread_;
+ // This is a pointer to the context owned by
+ // |offscreen_context_for_main_thread_|.
+ gpu::GLInProcessContext* wrapped_gl_context_for_main_thread_;
scoped_refptr<cc::ContextProvider> offscreen_context_for_compositor_thread_;
+
+ // |num_hardware_compositor_lock_| is updated on UI thread only but can be
+ // read on renderer main thread.
+ base::Lock num_hardware_compositor_lock_;
+ unsigned int num_hardware_compositors_;
};
+void SynchronousCompositorFactoryImpl::CompositorInitializedHardwareDraw(
+ SynchronousCompositorImpl* compositor) {
+ base::AutoLock lock(num_hardware_compositor_lock_);
+ num_hardware_compositors_++;
+}
+
+void SynchronousCompositorFactoryImpl::CompositorReleasedHardwareDraw(
+ SynchronousCompositorImpl* compositor) {
+ bool should_release_resources = false;
+ {
+ base::AutoLock lock(num_hardware_compositor_lock_);
+ DCHECK_GT(num_hardware_compositors_, 0u);
+ num_hardware_compositors_--;
+ should_release_resources = num_hardware_compositors_ == 0u;
+ }
+ if (should_release_resources)
+ ReleaseGlobalHardwareResources();
+}
+
+void SynchronousCompositorFactoryImpl::ReleaseGlobalHardwareResources() {
+ {
+ base::AutoLock lock(offscreen_context_for_compositor_thread_lock_);
+ offscreen_context_for_compositor_thread_ = NULL;
+ }
+
+ // TODO(boliu): Properly clean up command buffer server of main thread
+ // context here.
+}
+
+bool SynchronousCompositorFactoryImpl::CanCreateMainThreadContext() {
+ base::AutoLock lock(num_hardware_compositor_lock_);
+ return num_hardware_compositors_ > 0;
+}
+
base::LazyInstance<SynchronousCompositorFactoryImpl>::Leaky g_factory =
LAZY_INSTANCE_INITIALIZER;
@@ -155,27 +297,32 @@ bool SynchronousCompositorImpl::InitializeHwDraw(
scoped_refptr<gfx::GLSurface> surface) {
DCHECK(CalledOnValidThread());
DCHECK(output_surface_);
- return output_surface_->InitializeHwDraw(
+ bool success = output_surface_->InitializeHwDraw(
surface,
g_factory.Get().GetOffscreenContextProviderForCompositorThread());
+ if (success)
+ g_factory.Get().CompositorInitializedHardwareDraw(this);
+ return success;
}
void SynchronousCompositorImpl::ReleaseHwDraw() {
DCHECK(CalledOnValidThread());
DCHECK(output_surface_);
- return output_surface_->ReleaseHwDraw();
+ output_surface_->ReleaseHwDraw();
+ g_factory.Get().CompositorReleasedHardwareDraw(this);
}
bool SynchronousCompositorImpl::DemandDrawHw(
- gfx::Size view_size,
+ gfx::Size surface_size,
const gfx::Transform& transform,
- gfx::Rect damage_area,
+ gfx::Rect viewport,
+ gfx::Rect clip,
bool stencil_enabled) {
DCHECK(CalledOnValidThread());
DCHECK(output_surface_);
return output_surface_->DemandDrawHw(
- view_size, transform, damage_area, stencil_enabled);
+ surface_size, transform, viewport, clip, stencil_enabled);
}
bool SynchronousCompositorImpl::DemandDrawSw(SkCanvas* canvas) {
@@ -185,6 +332,14 @@ bool SynchronousCompositorImpl::DemandDrawSw(SkCanvas* canvas) {
return output_surface_->DemandDrawSw(canvas);
}
+void SynchronousCompositorImpl::SetMemoryPolicy(
+ const SynchronousCompositorMemoryPolicy& policy) {
+ DCHECK(CalledOnValidThread());
+ DCHECK(output_surface_);
+
+ return output_surface_->SetMemoryPolicy(policy);
+}
+
void SynchronousCompositorImpl::DidChangeRootLayerScrollOffset() {
if (input_handler_)
input_handler_->OnRootLayerDelegatedScrollOffsetChanged();
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 f0ea2c6e824..3189dcc983a 100644
--- a/chromium/content/browser/android/in_process/synchronous_compositor_impl.h
+++ b/chromium/content/browser/android/in_process/synchronous_compositor_impl.h
@@ -52,11 +52,14 @@ class SynchronousCompositorImpl
scoped_refptr<gfx::GLSurface> surface) OVERRIDE;
virtual void ReleaseHwDraw() OVERRIDE;
virtual bool DemandDrawHw(
- gfx::Size view_size,
+ gfx::Size surface_size,
const gfx::Transform& transform,
+ gfx::Rect viewport,
gfx::Rect clip,
bool stencil_enabled) OVERRIDE;
virtual bool DemandDrawSw(SkCanvas* canvas) OVERRIDE;
+ virtual void SetMemoryPolicy(
+ const SynchronousCompositorMemoryPolicy& policy) OVERRIDE;
virtual void DidChangeRootLayerScrollOffset() OVERRIDE;
// SynchronousCompositorOutputSurfaceDelegate
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 a6115e98994..28119a20329 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
@@ -9,33 +9,30 @@
#include "cc/output/begin_frame_args.h"
#include "cc/output/compositor_frame.h"
#include "cc/output/context_provider.h"
-#include "cc/output/managed_memory_policy.h"
#include "cc/output/output_surface_client.h"
#include "cc/output/software_output_device.h"
#include "content/browser/android/in_process/synchronous_compositor_impl.h"
-#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
#include "content/public/browser/browser_thread.h"
#include "gpu/command_buffer/client/gl_in_process_context.h"
+#include "third_party/skia/include/core/SkBitmapDevice.h"
#include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/core/SkDevice.h"
#include "ui/gfx/rect_conversions.h"
#include "ui/gfx/skia_util.h"
#include "ui/gfx/transform.h"
#include "ui/gl/gl_surface.h"
+#include "webkit/common/gpu/context_provider_in_process.h"
#include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
-
namespace content {
namespace {
-scoped_ptr<WebKit::WebGraphicsContext3D> CreateWebGraphicsContext3D(
- scoped_refptr<gfx::GLSurface> surface) {
+scoped_ptr<webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl>
+CreateWebGraphicsContext3D(scoped_refptr<gfx::GLSurface> surface) {
using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl;
if (!gfx::GLSurface::InitializeOneOff())
- return scoped_ptr<WebKit::WebGraphicsContext3D>();
+ return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>();
- const char* allowed_extensions = "*";
const gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;
WebKit::WebGraphicsContext3D::Attributes attributes;
@@ -49,16 +46,14 @@ scoped_ptr<WebKit::WebGraphicsContext3D> CreateWebGraphicsContext3D(
scoped_ptr<gpu::GLInProcessContext> context(
gpu::GLInProcessContext::CreateWithSurface(surface,
attributes.shareResources,
- allowed_extensions,
in_process_attribs,
gpu_preference));
if (!context.get())
- return scoped_ptr<WebKit::WebGraphicsContext3D>();
+ return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>();
- return scoped_ptr<WebKit::WebGraphicsContext3D>(
- WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext(
- context.Pass(), attributes));
+ return WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext(
+ context.Pass(), attributes).Pass();
}
void DidActivatePendingTree(int routing_id) {
@@ -98,7 +93,7 @@ class SynchronousCompositorOutputSurface::SoftwareDevice
private:
SynchronousCompositorOutputSurface* surface_;
- SkDevice null_device_;
+ SkBitmapDevice null_device_;
SkCanvas null_canvas_;
DISALLOW_COPY_AND_ASSIGN(SoftwareDevice);
@@ -112,7 +107,9 @@ SynchronousCompositorOutputSurface::SynchronousCompositorOutputSurface(
needs_begin_frame_(false),
invoking_composite_(false),
did_swap_buffer_(false),
- current_sw_canvas_(NULL) {
+ current_sw_canvas_(NULL),
+ memory_policy_(0),
+ output_surface_client_(NULL) {
capabilities_.deferred_gl_initialization = true;
capabilities_.draw_and_swap_full_viewport_every_frame = true;
capabilities_.adjust_deadline_for_parent = false;
@@ -140,21 +137,16 @@ bool SynchronousCompositorOutputSurface::BindToClient(
DCHECK(CalledOnValidThread());
if (!cc::OutputSurface::BindToClient(surface_client))
return false;
- surface_client->SetTreeActivationCallback(
+
+ output_surface_client_ = surface_client;
+ output_surface_client_->SetTreeActivationCallback(
base::Bind(&DidActivatePendingTree, routing_id_));
+ output_surface_client_->SetMemoryPolicy(memory_policy_);
+
SynchronousCompositorOutputSurfaceDelegate* delegate = GetDelegate();
if (delegate)
delegate->DidBindOutputSurface(this);
- const int bytes_limit = 64 * 1024 * 1024;
- const int num_resources_limit = 100;
- surface_client->SetMemoryPolicy(
- cc::ManagedMemoryPolicy(bytes_limit,
- cc::ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING,
- 0,
- cc::ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING,
- num_resources_limit));
-
return true;
}
@@ -175,9 +167,10 @@ void SynchronousCompositorOutputSurface::SetNeedsBeginFrame(
void SynchronousCompositorOutputSurface::SwapBuffers(
cc::CompositorFrame* frame) {
+ DCHECK(CalledOnValidThread());
if (!ForcedDrawToSoftwareDevice()) {
- DCHECK(context3d());
- context3d()->shallowFlushCHROMIUM();
+ DCHECK(context_provider_);
+ context_provider_->Context3d()->shallowFlushCHROMIUM();
}
SynchronousCompositorOutputSurfaceDelegate* delegate = GetDelegate();
if (delegate)
@@ -188,44 +181,45 @@ void SynchronousCompositorOutputSurface::SwapBuffers(
}
namespace {
-void AdjustTransformForClip(gfx::Transform* transform, gfx::Rect clip) {
- // The system-provided transform translates us from the screen origin to the
- // origin of the clip rect, but CC's draw origin starts at the clip.
- transform->matrix().postTranslate(-clip.x(), -clip.y(), 0);
+void AdjustTransform(gfx::Transform* transform, gfx::Rect viewport) {
+ // CC's draw origin starts at the viewport.
+ transform->matrix().postTranslate(-viewport.x(), -viewport.y(), 0);
}
} // namespace
bool SynchronousCompositorOutputSurface::InitializeHwDraw(
scoped_refptr<gfx::GLSurface> surface,
- scoped_refptr<cc::ContextProvider> offscreen_context) {
+ scoped_refptr<cc::ContextProvider> offscreen_context_provider) {
DCHECK(CalledOnValidThread());
DCHECK(HasClient());
- DCHECK(!context3d_);
+ DCHECK(!context_provider_);
DCHECK(surface);
- return InitializeAndSetContext3D(
- CreateWebGraphicsContext3D(surface).Pass(), offscreen_context);
+ scoped_refptr<cc::ContextProvider> onscreen_context_provider =
+ webkit::gpu::ContextProviderInProcess::Create(
+ CreateWebGraphicsContext3D(surface), "SynchronousCompositor");
+ return InitializeAndSetContext3d(onscreen_context_provider,
+ offscreen_context_provider);
}
void SynchronousCompositorOutputSurface::ReleaseHwDraw() {
+ DCHECK(CalledOnValidThread());
cc::OutputSurface::ReleaseGL();
}
bool SynchronousCompositorOutputSurface::DemandDrawHw(
gfx::Size surface_size,
const gfx::Transform& transform,
+ gfx::Rect viewport,
gfx::Rect clip,
bool stencil_enabled) {
DCHECK(CalledOnValidThread());
DCHECK(HasClient());
- DCHECK(context3d());
+ DCHECK(context_provider_);
- gfx::Transform adjusted_transform = transform;
- AdjustTransformForClip(&adjusted_transform, clip);
surface_size_ = surface_size;
- SetExternalDrawConstraints(adjusted_transform, clip);
SetExternalStencilTest(stencil_enabled);
- InvokeComposite(clip.size());
+ InvokeComposite(transform, viewport, clip, true);
return did_swap_buffer_;
}
@@ -242,29 +236,48 @@ bool SynchronousCompositorOutputSurface::DemandDrawSw(SkCanvas* canvas) {
gfx::Transform transform(gfx::Transform::kSkipInitialization);
transform.matrix() = canvas->getTotalMatrix(); // Converts 3x3 matrix to 4x4.
- AdjustTransformForClip(&transform, clip);
surface_size_ = gfx::Size(canvas->getDeviceSize().width(),
canvas->getDeviceSize().height());
- SetExternalDrawConstraints(transform, clip);
SetExternalStencilTest(false);
- InvokeComposite(clip.size());
+ InvokeComposite(transform, clip, clip, false);
return did_swap_buffer_;
}
void SynchronousCompositorOutputSurface::InvokeComposite(
- gfx::Size damage_size) {
+ const gfx::Transform& transform,
+ gfx::Rect viewport,
+ gfx::Rect clip,
+ bool valid_for_tile_management) {
DCHECK(!invoking_composite_);
base::AutoReset<bool> invoking_composite_resetter(&invoking_composite_, true);
did_swap_buffer_ = false;
- SetNeedsRedrawRect(gfx::Rect(damage_size));
+
+ gfx::Transform adjusted_transform = transform;
+ AdjustTransform(&adjusted_transform, viewport);
+ SetExternalDrawConstraints(
+ adjusted_transform, viewport, clip, valid_for_tile_management);
+ SetNeedsRedrawRect(gfx::Rect(viewport.size()));
+
if (needs_begin_frame_)
BeginFrame(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
+ // properly.
+ if (valid_for_tile_management) {
+ cached_hw_transform_ = adjusted_transform;
+ cached_hw_viewport_ = viewport;
+ cached_hw_clip_ = clip;
+ } else {
+ SetExternalDrawConstraints(
+ cached_hw_transform_, cached_hw_viewport_, cached_hw_clip_, true);
+ }
+
if (did_swap_buffer_)
- OnSwapBuffersComplete(NULL);
+ OnSwapBuffersComplete();
}
void SynchronousCompositorOutputSurface::PostCheckForRetroactiveBeginFrame() {
@@ -272,6 +285,16 @@ void SynchronousCompositorOutputSurface::PostCheckForRetroactiveBeginFrame() {
// intentionally no-op here.
}
+void SynchronousCompositorOutputSurface::SetMemoryPolicy(
+ const SynchronousCompositorMemoryPolicy& policy) {
+ DCHECK(CalledOnValidThread());
+ memory_policy_.bytes_limit_when_visible = policy.bytes_limit;
+ memory_policy_.num_resources_limit = policy.num_resources_limit;
+
+ if (output_surface_client_)
+ output_surface_client_->SetMemoryPolicy(memory_policy_);
+}
+
// Not using base::NonThreadSafe as we want to enforce a more exacting threading
// requirement: SynchronousCompositorOutputSurface() must only be used on the UI
// thread.
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 3ab149818ae..b9b4d678c09 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
@@ -9,8 +9,10 @@
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "cc/output/managed_memory_policy.h"
#include "cc/output/output_surface.h"
#include "content/public/browser/android/synchronous_compositor.h"
+#include "ui/gfx/transform.h"
namespace cc {
class ContextProvider;
@@ -63,13 +65,15 @@ class SynchronousCompositorOutputSurface
// Partial SynchronousCompositor API implementation.
bool InitializeHwDraw(
scoped_refptr<gfx::GLSurface> surface,
- scoped_refptr<cc::ContextProvider> offscreen_context);
+ scoped_refptr<cc::ContextProvider> offscreen_context_provider);
void ReleaseHwDraw();
bool DemandDrawHw(gfx::Size surface_size,
const gfx::Transform& transform,
+ gfx::Rect viewport,
gfx::Rect clip,
bool stencil_enabled);
bool DemandDrawSw(SkCanvas* canvas);
+ void SetMemoryPolicy(const SynchronousCompositorMemoryPolicy& policy);
private:
class SoftwareDevice;
@@ -78,7 +82,10 @@ class SynchronousCompositorOutputSurface
// Private OutputSurface overrides.
virtual void PostCheckForRetroactiveBeginFrame() OVERRIDE;
- void InvokeComposite(gfx::Size damage_size);
+ void InvokeComposite(const gfx::Transform& transform,
+ gfx::Rect viewport,
+ gfx::Rect clip,
+ bool valid_for_tile_management);
bool CalledOnValidThread() const;
SynchronousCompositorOutputSurfaceDelegate* GetDelegate();
@@ -87,9 +94,17 @@ class SynchronousCompositorOutputSurface
bool invoking_composite_;
bool did_swap_buffer_;
+ gfx::Transform cached_hw_transform_;
+ gfx::Rect cached_hw_viewport_;
+ gfx::Rect cached_hw_clip_;
+
// Only valid (non-NULL) during a DemandDrawSw() call.
SkCanvas* current_sw_canvas_;
+ cc::ManagedMemoryPolicy memory_policy_;
+
+ cc::OutputSurfaceClient* output_surface_client_;
+
DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorOutputSurface);
};
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 17c909d42d9..34144dac579 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
@@ -8,7 +8,7 @@
#include "cc/input/input_handler.h"
#include "content/browser/android/in_process/synchronous_compositor_impl.h"
#include "content/public/browser/browser_thread.h"
-#include "ui/base/latency_info.h"
+#include "ui/events/latency_info.h"
using WebKit::WebInputEvent;
diff --git a/chromium/content/browser/android/overscroll_glow.cc b/chromium/content/browser/android/overscroll_glow.cc
index 2c9efeea72d..6adf7dbec48 100644
--- a/chromium/content/browser/android/overscroll_glow.cc
+++ b/chromium/content/browser/android/overscroll_glow.cc
@@ -65,13 +65,14 @@ gfx::Vector2dF ZeroSmallComponents(gfx::Vector2dF vector) {
} // namespace
-scoped_ptr<OverscrollGlow> OverscrollGlow::Create(bool enabled) {
+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>();
- return make_scoped_ptr(new OverscrollGlow(enabled, edge, glow));
+ return make_scoped_ptr(new OverscrollGlow(enabled, size, edge, glow));
}
void OverscrollGlow::EnsureResources() {
@@ -79,9 +80,11 @@ void OverscrollGlow::EnsureResources() {
}
OverscrollGlow::OverscrollGlow(bool enabled,
+ gfx::SizeF size,
const SkBitmap& edge,
const SkBitmap& glow)
: enabled_(enabled),
+ size_(size),
horizontal_overscroll_enabled_(true),
vertical_overscroll_enabled_(true),
root_layer_(cc::Layer::Create()) {
diff --git a/chromium/content/browser/android/overscroll_glow.h b/chromium/content/browser/android/overscroll_glow.h
index 4ea929e9d3e..01156a23f03 100644
--- a/chromium/content/browser/android/overscroll_glow.h
+++ b/chromium/content/browser/android/overscroll_glow.h
@@ -30,7 +30,7 @@ class OverscrollGlow {
// 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);
+ static scoped_ptr<OverscrollGlow> Create(bool enabled, gfx::SizeF size);
// Force loading of any necessary resources. This function is thread-safe.
static void EnsureResources();
@@ -79,7 +79,10 @@ class OverscrollGlow {
private:
enum Axis { AXIS_X, AXIS_Y };
- OverscrollGlow(bool enabled, const SkBitmap& edge, const SkBitmap& glow);
+ OverscrollGlow(bool enabled,
+ gfx::SizeF size,
+ const SkBitmap& edge,
+ const SkBitmap& glow);
void Pull(base::TimeTicks current_time,
gfx::Vector2dF added_overscroll);
diff --git a/chromium/content/browser/android/surface_texture_peer_browser_impl.cc b/chromium/content/browser/android/surface_texture_peer_browser_impl.cc
index faaf4a2821d..7935c9ab409 100644
--- a/chromium/content/browser/android/surface_texture_peer_browser_impl.cc
+++ b/chromium/content/browser/android/surface_texture_peer_browser_impl.cc
@@ -4,11 +4,11 @@
#include "content/browser/android/surface_texture_peer_browser_impl.h"
+#include "content/browser/media/android/browser_media_player_manager.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.h"
#include "media/base/android/media_player_android.h"
-#include "media/base/android/media_player_manager.h"
#include "ui/gl/android/scoped_java_surface.h"
namespace content {
@@ -18,7 +18,7 @@ namespace {
// Pass a java surface object to the MediaPlayerAndroid object
// identified by render process handle, render view ID and player ID.
static void SetSurfacePeer(
- scoped_refptr<gfx::SurfaceTextureBridge> surface_texture_bridge,
+ scoped_refptr<gfx::SurfaceTexture> surface_texture,
base::ProcessHandle render_process_handle,
int render_view_id,
int player_id) {
@@ -40,7 +40,7 @@ static void SetSurfacePeer(
host->media_player_manager()->GetPlayer(player_id);
if (player &&
player != host->media_player_manager()->GetFullscreenPlayer()) {
- gfx::ScopedJavaSurface surface(surface_texture_bridge.get());
+ gfx::ScopedJavaSurface surface(surface_texture.get());
player->SetVideoSurface(surface.Pass());
}
}
@@ -57,14 +57,14 @@ SurfaceTexturePeerBrowserImpl::~SurfaceTexturePeerBrowserImpl() {
void SurfaceTexturePeerBrowserImpl::EstablishSurfaceTexturePeer(
base::ProcessHandle render_process_handle,
- scoped_refptr<gfx::SurfaceTextureBridge> surface_texture_bridge,
+ scoped_refptr<gfx::SurfaceTexture> surface_texture,
int render_view_id,
int player_id) {
- if (!surface_texture_bridge.get())
+ if (!surface_texture.get())
return;
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
- &SetSurfacePeer, surface_texture_bridge, render_process_handle,
+ &SetSurfacePeer, surface_texture, render_process_handle,
render_view_id, player_id));
}
diff --git a/chromium/content/browser/android/surface_texture_peer_browser_impl.h b/chromium/content/browser/android/surface_texture_peer_browser_impl.h
index 644bf2c92e0..4aa85634dc2 100644
--- a/chromium/content/browser/android/surface_texture_peer_browser_impl.h
+++ b/chromium/content/browser/android/surface_texture_peer_browser_impl.h
@@ -24,7 +24,7 @@ class SurfaceTexturePeerBrowserImpl : public SurfaceTexturePeer {
// SurfaceTexturePeer implementation.
virtual void EstablishSurfaceTexturePeer(
base::ProcessHandle render_process_handle,
- scoped_refptr<gfx::SurfaceTextureBridge> surface_texture_bridge,
+ scoped_refptr<gfx::SurfaceTexture> surface_texture,
int render_view_id,
int player_id) OVERRIDE;
diff --git a/chromium/content/browser/android/tracing_intent_handler.cc b/chromium/content/browser/android/tracing_intent_handler.cc
index 276091619cc..324f8055cc1 100644
--- a/chromium/content/browser/android/tracing_intent_handler.cc
+++ b/chromium/content/browser/android/tracing_intent_handler.cc
@@ -16,7 +16,7 @@ namespace content {
TracingIntentHandler* g_trace_intent_handler = NULL;
TracingIntentHandler::TracingIntentHandler(const base::FilePath& path)
- : TraceSubscriberStdio(path) {
+ : TraceSubscriberStdio(path, FILE_TYPE_ARRAY, false) {
TraceController::GetInstance()->BeginTracing(
this,
std::string("-test*"),
diff --git a/chromium/content/browser/android/web_contents_observer_android.cc b/chromium/content/browser/android/web_contents_observer_android.cc
index eac49b240ae..e30bf953304 100644
--- a/chromium/content/browser/android/web_contents_observer_android.cc
+++ b/chromium/content/browser/android/web_contents_observer_android.cc
@@ -67,8 +67,8 @@ void WebContentsObserverAndroid::DidStartLoading(
ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
if (obj.is_null())
return;
- ScopedJavaLocalRef<jstring> jstring_url(
- ConvertUTF8ToJavaString(env, web_contents()->GetURL().spec()));
+ ScopedJavaLocalRef<jstring> jstring_url(ConvertUTF8ToJavaString(
+ env, web_contents()->GetVisibleURL().spec()));
Java_WebContentsObserverAndroid_didStartLoading(
env, obj.obj(), jstring_url.obj());
}
@@ -87,7 +87,7 @@ void WebContentsObserverAndroid::DidStopLoading(
if (entry && !entry->GetBaseURLForDataURL().is_empty()) {
url_string = entry->GetBaseURLForDataURL().possibly_invalid_spec();
} else {
- url_string = web_contents()->GetURL().spec();
+ url_string = web_contents()->GetLastCommittedURL().spec();
}
ScopedJavaLocalRef<jstring> jstring_url(
@@ -212,6 +212,22 @@ void WebContentsObserverAndroid::DidChangeVisibleSSLState() {
Java_WebContentsObserverAndroid_didChangeVisibleSSLState(env, obj.obj());
}
+void WebContentsObserverAndroid::DidAttachInterstitialPage() {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
+ if (obj.is_null())
+ return;
+ Java_WebContentsObserverAndroid_didAttachInterstitialPage(env, obj.obj());
+}
+
+void WebContentsObserverAndroid::DidDetachInterstitialPage() {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
+ if (obj.is_null())
+ return;
+ Java_WebContentsObserverAndroid_didDetachInterstitialPage(env, obj.obj());
+}
+
void WebContentsObserverAndroid::DidFailLoadInternal(
bool is_provisional_load,
bool is_main_frame,
diff --git a/chromium/content/browser/android/web_contents_observer_android.h b/chromium/content/browser/android/web_contents_observer_android.h
index 35e5526148c..e975d795260 100644
--- a/chromium/content/browser/android/web_contents_observer_android.h
+++ b/chromium/content/browser/android/web_contents_observer_android.h
@@ -70,6 +70,8 @@ class WebContentsObserverAndroid : public WebContentsObserver {
RenderViewHost* render_view_host) OVERRIDE;
virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE;
virtual void DidChangeVisibleSSLState() OVERRIDE;
+ virtual void DidAttachInterstitialPage() OVERRIDE;
+ virtual void DidDetachInterstitialPage() OVERRIDE;
void DidFailLoadInternal(bool is_provisional_load,
bool is_main_frame,
diff --git a/chromium/content/browser/aura/browser_compositor_output_surface.cc b/chromium/content/browser/aura/browser_compositor_output_surface.cc
index 11fbe0c42a9..36e5dcdbfda 100644
--- a/chromium/content/browser/aura/browser_compositor_output_surface.cc
+++ b/chromium/content/browser/aura/browser_compositor_output_surface.cc
@@ -11,6 +11,7 @@
#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"
@@ -18,12 +19,12 @@
namespace content {
BrowserCompositorOutputSurface::BrowserCompositorOutputSurface(
- scoped_ptr<WebKit::WebGraphicsContext3D> context,
+ const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
int surface_id,
IDMap<BrowserCompositorOutputSurface>* output_surface_map,
base::MessageLoopProxy* compositor_message_loop,
base::WeakPtr<ui::Compositor> compositor)
- : OutputSurface(context.Pass()),
+ : OutputSurface(context_provider),
surface_id_(surface_id),
output_surface_map_(output_surface_map),
compositor_message_loop_(compositor_message_loop),
@@ -70,12 +71,13 @@ void BrowserCompositorOutputSurface::Reshape(gfx::Size size,
void BrowserCompositorOutputSurface::SwapBuffers(cc::CompositorFrame* frame) {
DCHECK(frame->gl_frame_data);
- WebGraphicsContext3DCommandBufferImpl* command_buffer =
- static_cast<WebGraphicsContext3DCommandBufferImpl*>(context3d());
+ WebGraphicsContext3DCommandBufferImpl* command_buffer_context =
+ static_cast<WebGraphicsContext3DCommandBufferImpl*>(
+ context_provider_->Context3d());
CommandBufferProxyImpl* command_buffer_proxy =
- command_buffer->GetCommandBufferProxy();
+ command_buffer_context->GetCommandBufferProxy();
DCHECK(command_buffer_proxy);
- context3d()->shallowFlushCHROMIUM();
+ context_provider_->Context3d()->shallowFlushCHROMIUM();
command_buffer_proxy->SetLatencyInfo(frame->metadata.latency_info);
if (reflector_.get()) {
diff --git a/chromium/content/browser/aura/browser_compositor_output_surface.h b/chromium/content/browser/aura/browser_compositor_output_surface.h
index 4b891bdc2ef..f9ec3c8d9d5 100644
--- a/chromium/content/browser/aura/browser_compositor_output_surface.h
+++ b/chromium/content/browser/aura/browser_compositor_output_surface.h
@@ -15,7 +15,9 @@ namespace base { class MessageLoopProxy; }
namespace ui { class Compositor; }
namespace content {
+class ContextProviderCommandBuffer;
class ReflectorImpl;
+class WebGraphicsContext3DCommandBufferImpl;
// Adapts a WebGraphicsContext3DCommandBufferImpl into a
// cc::OutputSurface that also handles vsync parameter updates
@@ -25,7 +27,7 @@ class BrowserCompositorOutputSurface
public base::NonThreadSafe {
public:
BrowserCompositorOutputSurface(
- scoped_ptr<WebKit::WebGraphicsContext3D> context,
+ const scoped_refptr<ContextProviderCommandBuffer>& context,
int surface_id,
IDMap<BrowserCompositorOutputSurface>* output_surface_map,
base::MessageLoopProxy* compositor_message_loop,
diff --git a/chromium/content/browser/aura/compositor_resize_lock.cc b/chromium/content/browser/aura/compositor_resize_lock.cc
new file mode 100644
index 00000000000..e80baba5642
--- /dev/null
+++ b/chromium/content/browser/aura/compositor_resize_lock.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/aura/compositor_resize_lock.h"
+
+#include "base/debug/trace_event.h"
+#include "content/public/browser/browser_thread.h"
+#include "ui/aura/root_window.h"
+#include "ui/compositor/compositor.h"
+
+namespace content {
+
+CompositorResizeLock::CompositorResizeLock(aura::RootWindow* root_window,
+ const gfx::Size new_size,
+ bool defer_compositor_lock,
+ const base::TimeDelta& timeout)
+ : ResizeLock(new_size, defer_compositor_lock),
+ root_window_(root_window),
+ weak_ptr_factory_(this),
+ cancelled_(false) {
+ DCHECK(root_window_);
+
+ TRACE_EVENT_ASYNC_BEGIN2("ui", "CompositorResizeLock", this,
+ "width", expected_size().width(),
+ "height", expected_size().height());
+ root_window_->HoldPointerMoves();
+
+ BrowserThread::PostDelayedTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&CompositorResizeLock::CancelLock,
+ weak_ptr_factory_.GetWeakPtr()),
+ timeout);
+}
+
+CompositorResizeLock::~CompositorResizeLock() {
+ CancelLock();
+ TRACE_EVENT_ASYNC_END2("ui", "CompositorResizeLock", this,
+ "width", expected_size().width(),
+ "height", expected_size().height());
+}
+
+bool CompositorResizeLock::GrabDeferredLock() {
+ return ResizeLock::GrabDeferredLock();
+}
+
+void CompositorResizeLock::UnlockCompositor() {
+ ResizeLock::UnlockCompositor();
+ compositor_lock_ = NULL;
+}
+
+void CompositorResizeLock::LockCompositor() {
+ ResizeLock::LockCompositor();
+ compositor_lock_ = root_window_->compositor()->GetCompositorLock();
+}
+
+void CompositorResizeLock::CancelLock() {
+ if (cancelled_)
+ return;
+ cancelled_ = true;
+ UnlockCompositor();
+ root_window_->ReleasePointerMoves();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/aura/compositor_resize_lock.h b/chromium/content/browser/aura/compositor_resize_lock.h
new file mode 100644
index 00000000000..51787e49393
--- /dev/null
+++ b/chromium/content/browser/aura/compositor_resize_lock.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_AURA_RESIZE_LOCK_AURA_H_
+#define CONTENT_BROWSER_AURA_RESIZE_LOCK_AURA_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+#include "content/browser/aura/resize_lock.h"
+
+namespace aura { class RootWindow; }
+
+namespace ui { class CompositorLock; }
+
+namespace content {
+
+// Used to prevent further resizes while a resize is pending.
+class CompositorResizeLock : public ResizeLock {
+ public:
+ CompositorResizeLock(aura::RootWindow* root_window,
+ const gfx::Size new_size,
+ bool defer_compositor_lock,
+ const base::TimeDelta& timeout);
+ virtual ~CompositorResizeLock();
+
+ virtual bool GrabDeferredLock() OVERRIDE;
+ virtual void UnlockCompositor() OVERRIDE;
+
+ protected:
+ virtual void LockCompositor() OVERRIDE;
+ void CancelLock();
+
+ private:
+ aura::RootWindow* root_window_;
+ scoped_refptr<ui::CompositorLock> compositor_lock_;
+ base::WeakPtrFactory<CompositorResizeLock> weak_ptr_factory_;
+ bool cancelled_;
+
+ DISALLOW_COPY_AND_ASSIGN(CompositorResizeLock);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_AURA_RESIZE_LOCK_AURA_H_
diff --git a/chromium/content/browser/aura/gpu_process_transport_factory.cc b/chromium/content/browser/aura/gpu_process_transport_factory.cc
index 47b1533ae77..959210decea 100644
--- a/chromium/content/browser/aura/gpu_process_transport_factory.cc
+++ b/chromium/content/browser/aura/gpu_process_transport_factory.cc
@@ -10,6 +10,7 @@
#include "base/command_line.h"
#include "base/location.h"
#include "base/message_loop/message_loop.h"
+#include "base/metrics/histogram.h"
#include "cc/output/compositor_frame.h"
#include "cc/output/output_surface.h"
#include "content/browser/aura/browser_compositor_output_surface.h"
@@ -74,6 +75,7 @@ class OwnedTexture : public ui::Texture, ImageTransportFactoryObserver {
// ImageTransportFactory overrides:
virtual void OnLostResources() OVERRIDE {
DeleteTexture();
+ host_context_ = NULL;
}
protected:
@@ -90,9 +92,8 @@ class OwnedTexture : public ui::Texture, ImageTransportFactoryObserver {
}
}
- // A raw pointer. This |ImageTransportClientTexture| will be destroyed
- // before the |host_context_| via
- // |ImageTransportFactoryObserver::OnLostContext()| handlers.
+ // The OnLostResources() callback will happen before this context
+ // pointer is destroyed.
WebKit::WebGraphicsContext3D* host_context_;
unsigned texture_id_;
@@ -199,12 +200,6 @@ GpuProcessTransportFactory::CreateOffscreenCommandBufferContext() {
return CreateContextCommon(swap_client, 0);
}
-scoped_ptr<WebKit::WebGraphicsContext3D>
-GpuProcessTransportFactory::CreateOffscreenContext() {
- return CreateOffscreenCommandBufferContext()
- .PassAs<WebKit::WebGraphicsContext3D>();
-}
-
scoped_ptr<cc::SoftwareOutputDevice> CreateSoftwareOutputDevice(
ui::Compositor* compositor) {
#if defined(OS_WIN)
@@ -225,15 +220,22 @@ scoped_ptr<cc::OutputSurface> GpuProcessTransportFactory::CreateOutputSurface(
if (!data)
data = CreatePerCompositorData(compositor);
- scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context;
+ scoped_refptr<ContextProviderCommandBuffer> context_provider;
+
CommandLine* command_line = CommandLine::ForCurrentProcess();
if (!command_line->HasSwitch(switches::kUIEnableSoftwareCompositing)) {
- context =
- CreateContextCommon(data->swap_client->AsWeakPtr(), data->surface_id);
+ context_provider = ContextProviderCommandBuffer::Create(
+ GpuProcessTransportFactory::CreateContextCommon(
+ data->swap_client->AsWeakPtr(),
+ data->surface_id),
+ "Compositor");
}
- if (!context) {
+
+ UMA_HISTOGRAM_BOOLEAN("Aura.CreatedGpuBrowserCompositor", !!context_provider);
+
+ if (!context_provider.get()) {
if (ui::Compositor::WasInitializedWithThread()) {
- LOG(FATAL) << "Failed to create UI context, but can't use software "
+ LOG(FATAL) << "Failed to create UI context, but can't use software"
" compositing with browser threaded compositing. Aborting.";
}
@@ -255,7 +257,7 @@ scoped_ptr<cc::OutputSurface> GpuProcessTransportFactory::CreateOutputSurface(
scoped_ptr<BrowserCompositorOutputSurface> surface(
new BrowserCompositorOutputSurface(
- context.PassAs<WebKit::WebGraphicsContext3D>(),
+ context_provider,
per_compositor_data_[compositor]->surface_id,
&output_surface_map_,
base::MessageLoopProxy::current().get(),
@@ -390,12 +392,14 @@ void GpuProcessTransportFactory::RemoveObserver(
scoped_refptr<cc::ContextProvider>
GpuProcessTransportFactory::OffscreenContextProviderForMainThread() {
- if (!shared_contexts_main_thread_.get() ||
- shared_contexts_main_thread_->DestroyedOnMainThread()) {
+ // 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(
- base::Bind(&GpuProcessTransportFactory::
- CreateOffscreenCommandBufferContext,
- base::Unretained(this)));
+ GpuProcessTransportFactory::CreateOffscreenCommandBufferContext(),
+ "Compositor-Offscreen-MainThread");
if (shared_contexts_main_thread_) {
shared_contexts_main_thread_->SetLostContextCallback(base::Bind(
&GpuProcessTransportFactory::
@@ -411,12 +415,13 @@ GpuProcessTransportFactory::OffscreenContextProviderForMainThread() {
scoped_refptr<cc::ContextProvider>
GpuProcessTransportFactory::OffscreenContextProviderForCompositorThread() {
- if (!shared_contexts_compositor_thread_.get() ||
- shared_contexts_compositor_thread_->DestroyedOnMainThread()) {
+ // 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(
- base::Bind(&GpuProcessTransportFactory::
- CreateOffscreenCommandBufferContext,
- base::Unretained(this)));
+ GpuProcessTransportFactory::CreateOffscreenCommandBufferContext(),
+ "Compositor-Offscreen");
}
return shared_contexts_compositor_thread_;
}
@@ -500,18 +505,29 @@ void GpuProcessTransportFactory::OnLostMainThreadSharedContextInsideCallback() {
void GpuProcessTransportFactory::OnLostMainThreadSharedContext() {
LOG(ERROR) << "Lost UI shared context.";
+
// Keep old resources around while we call the observers, but ensure that
// 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<ContextProviderCommandBuffer> old_contexts_main_thread =
+ 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_ptr<GLHelper> old_helper(gl_helper_.release());
+ scoped_ptr<GLHelper> lost_gl_helper = gl_helper_.Pass();
FOR_EACH_OBSERVER(ImageTransportFactoryObserver,
observer_list_,
OnLostResources());
+
+ // 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;
}
} // 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 72b88d532bb..56d3e55498a 100644
--- a/chromium/content/browser/aura/gpu_process_transport_factory.h
+++ b/chromium/content/browser/aura/gpu_process_transport_factory.h
@@ -35,9 +35,7 @@ class GpuProcessTransportFactory
scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
CreateOffscreenCommandBufferContext();
- // ContextFactory implementation.
- virtual scoped_ptr<WebKit::WebGraphicsContext3D> CreateOffscreenContext()
- OVERRIDE;
+ // ui::ContextFactory implementation.
virtual scoped_ptr<cc::OutputSurface> CreateOutputSurface(
ui::Compositor* compositor) OVERRIDE;
virtual scoped_refptr<ui::Reflector> CreateReflector(
@@ -46,6 +44,10 @@ class GpuProcessTransportFactory
virtual void RemoveReflector(
scoped_refptr<ui::Reflector> reflector) OVERRIDE;
virtual void RemoveCompositor(ui::Compositor* compositor) OVERRIDE;
+ virtual scoped_refptr<cc::ContextProvider>
+ OffscreenContextProviderForMainThread() OVERRIDE;
+ virtual scoped_refptr<cc::ContextProvider>
+ OffscreenContextProviderForCompositorThread() OVERRIDE;
virtual bool DoesCreateTestContexts() OVERRIDE;
// ImageTransportFactory implementation.
@@ -66,12 +68,6 @@ class GpuProcessTransportFactory
virtual void RemoveObserver(
ImageTransportFactoryObserver* observer) OVERRIDE;
- // ui::ContextFactory implementation.
- virtual scoped_refptr<cc::ContextProvider>
- OffscreenContextProviderForMainThread() OVERRIDE;
- virtual scoped_refptr<cc::ContextProvider>
- OffscreenContextProviderForCompositorThread() OVERRIDE;
-
void OnLostContext(ui::Compositor* compositor);
private:
diff --git a/chromium/content/browser/aura/image_transport_factory.cc b/chromium/content/browser/aura/image_transport_factory.cc
index 28b04bf7ea4..e38ae880bbb 100644
--- a/chromium/content/browser/aura/image_transport_factory.cc
+++ b/chromium/content/browser/aura/image_transport_factory.cc
@@ -44,6 +44,7 @@ static bool UseTestContextAndTransportFactory() {
// static
void ImageTransportFactory::Initialize() {
+ DCHECK(!g_factory);
if (UseTestContextAndTransportFactory()) {
g_factory =
new NoTransportImageTransportFactory(new ui::TestContextFactory);
@@ -53,6 +54,12 @@ void ImageTransportFactory::Initialize() {
ui::ContextFactory::SetInstance(g_factory->AsContextFactory());
}
+void ImageTransportFactory::InitializeForUnitTests() {
+ DCHECK(!g_factory);
+ g_factory = new NoTransportImageTransportFactory(new ui::TestContextFactory);
+ ui::ContextFactory::SetInstance(g_factory->AsContextFactory());
+}
+
// static
void ImageTransportFactory::Terminate() {
ui::ContextFactory::SetInstance(NULL);
diff --git a/chromium/content/browser/aura/image_transport_factory.h b/chromium/content/browser/aura/image_transport_factory.h
index 85fba7d5300..7cd2523c421 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 "content/common/content_export.h"
#include "ui/gfx/native_widget_types.h"
namespace gfx {
@@ -27,7 +28,7 @@ namespace content {
class GLHelper;
// This class provides a way to get notified when surface handles get lost.
-class ImageTransportFactoryObserver {
+class CONTENT_EXPORT ImageTransportFactoryObserver {
public:
virtual ~ImageTransportFactoryObserver() {}
@@ -44,13 +45,17 @@ class ImageTransportFactoryObserver {
// cross-process image transport, both for creating the shared surface handle
// (destination surface for the GPU process) and the transport client (logic for
// using that surface as a texture). The factory is a process-wide singleton.
-class ImageTransportFactory {
+class CONTENT_EXPORT ImageTransportFactory {
public:
virtual ~ImageTransportFactory() {}
- // Initialize the global transport factory.
+ // Initializes the global transport factory.
static void Initialize();
+ // Initializes the global transport factory for unit tests, using a test
+ // context.
+ static void InitializeForUnitTests();
+
// Terminates the global transport factory.
static void Terminate();
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 18e8dad9072..6fa80c69095 100644
--- a/chromium/content/browser/aura/no_transport_image_transport_factory.cc
+++ b/chromium/content/browser/aura/no_transport_image_transport_factory.cc
@@ -3,13 +3,51 @@
// found in the LICENSE file.
#include "content/browser/aura/no_transport_image_transport_factory.h"
+
+#include "cc/output/context_provider.h"
+#include "content/common/gpu/client/gl_helper.h"
+#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
#include "ui/compositor/compositor.h"
namespace content {
+namespace {
+
+class FakeTexture : public ui::Texture {
+ public:
+ FakeTexture(scoped_refptr<cc::ContextProvider> context_provider,
+ float device_scale_factor)
+ : ui::Texture(false, gfx::Size(), device_scale_factor),
+ context_provider_(context_provider),
+ 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 {
+ size_ = new_size;
+ }
+
+ private:
+ virtual ~FakeTexture() {
+ context_provider_->Context3d()->deleteTexture(texture_);
+ }
+
+ scoped_refptr<cc::ContextProvider> context_provider_;
+ unsigned texture_;
+ DISALLOW_COPY_AND_ASSIGN(FakeTexture);
+};
+
+} // anonymous namespace
+
NoTransportImageTransportFactory::NoTransportImageTransportFactory(
ui::ContextFactory* context_factory)
- : context_factory_(context_factory) {}
+ : context_factory_(context_factory),
+ context_provider_(
+ context_factory_->OffscreenContextProviderForMainThread()) {}
NoTransportImageTransportFactory::~NoTransportImageTransportFactory() {}
@@ -28,7 +66,7 @@ void NoTransportImageTransportFactory::DestroySharedSurfaceHandle(
scoped_refptr<ui::Texture>
NoTransportImageTransportFactory::CreateTransportClient(
float device_scale_factor) {
- return NULL;
+ return new FakeTexture(context_provider_, device_scale_factor);
}
scoped_refptr<ui::Texture> NoTransportImageTransportFactory::CreateOwnedTexture(
@@ -38,7 +76,11 @@ scoped_refptr<ui::Texture> NoTransportImageTransportFactory::CreateOwnedTexture(
return NULL;
}
-GLHelper* NoTransportImageTransportFactory::GetGLHelper() { return NULL; }
+GLHelper* NoTransportImageTransportFactory::GetGLHelper() {
+ if (!gl_helper_)
+ gl_helper_.reset(new GLHelper(context_provider_->Context3d()));
+ return gl_helper_.get();
+}
uint32 NoTransportImageTransportFactory::InsertSyncPoint() { return 0; }
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 8254faf5fa5..0d571643afd 100644
--- a/chromium/content/browser/aura/no_transport_image_transport_factory.h
+++ b/chromium/content/browser/aura/no_transport_image_transport_factory.h
@@ -8,6 +8,10 @@
#include "base/memory/scoped_ptr.h"
#include "content/browser/aura/image_transport_factory.h"
+namespace cc {
+class ContextProvider;
+}
+
namespace content {
// An ImageTransportFactory that disables transport.
@@ -36,6 +40,8 @@ class NoTransportImageTransportFactory : public ImageTransportFactory {
private:
scoped_ptr<ui::ContextFactory> context_factory_;
+ scoped_refptr<cc::ContextProvider> context_provider_;
+ scoped_ptr<GLHelper> gl_helper_;
DISALLOW_COPY_AND_ASSIGN(NoTransportImageTransportFactory);
};
diff --git a/chromium/content/browser/aura/reflector_impl.cc b/chromium/content/browser/aura/reflector_impl.cc
index 1e26cf8d18e..78726ecdcc2 100644
--- a/chromium/content/browser/aura/reflector_impl.cc
+++ b/chromium/content/browser/aura/reflector_impl.cc
@@ -68,7 +68,8 @@ void ReflectorImpl::ShutdownOnImplThread() {
// ImplThread.
void ReflectorImpl::AttachToOutputSurface(
BrowserCompositorOutputSurface* output_surface) {
- gl_helper_.reset(new GLHelper(output_surface->context3d()));
+ gl_helper_.reset(
+ new GLHelper(output_surface->context_provider()->Context3d()));
output_surface->SetReflector(this);
}
diff --git a/chromium/content/browser/aura/resize_lock.cc b/chromium/content/browser/aura/resize_lock.cc
new file mode 100644
index 00000000000..4c8cd95a67f
--- /dev/null
+++ b/chromium/content/browser/aura/resize_lock.cc
@@ -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.
+
+#include "content/browser/aura/resize_lock.h"
+
+namespace content {
+
+ResizeLock::ResizeLock(const gfx::Size new_size, bool defer_compositor_lock)
+ : new_size_(new_size),
+ defer_compositor_lock_(defer_compositor_lock) {
+ if (!defer_compositor_lock_)
+ LockCompositor();
+}
+
+ResizeLock::~ResizeLock() {
+ UnlockCompositor();
+}
+
+bool ResizeLock::GrabDeferredLock() {
+ if (!defer_compositor_lock_)
+ return false;
+ LockCompositor();
+ return true;
+}
+
+void ResizeLock::UnlockCompositor() {
+ defer_compositor_lock_ = false;
+}
+
+void ResizeLock::LockCompositor() {
+ defer_compositor_lock_ = false;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/aura/resize_lock.h b/chromium/content/browser/aura/resize_lock.h
new file mode 100644
index 00000000000..cff98224c7f
--- /dev/null
+++ b/chromium/content/browser/aura/resize_lock.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_AURA_RESIZE_LOCK_H_
+#define CONTENT_BROWSER_AURA_RESIZE_LOCK_H_
+
+#include "base/basictypes.h"
+#include "content/common/content_export.h"
+#include "ui/gfx/size.h"
+
+namespace content {
+
+class CONTENT_EXPORT ResizeLock {
+ public:
+ virtual ~ResizeLock();
+
+ virtual bool GrabDeferredLock();
+ virtual void UnlockCompositor();
+
+ const gfx::Size& expected_size() const { return new_size_; }
+
+ protected:
+ ResizeLock(const gfx::Size new_size, bool defer_compositor_lock);
+
+ virtual void LockCompositor();
+
+ private:
+ gfx::Size new_size_;
+ bool defer_compositor_lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(ResizeLock);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_AURA_RESIZE_LOCK_H_
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 c59806e83f9..1f92582841e 100644
--- a/chromium/content/browser/aura/software_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/aura/software_browser_compositor_output_surface.cc
@@ -8,7 +8,7 @@
#include "cc/output/compositor_frame.h"
#include "cc/output/software_output_device.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "ui/base/latency_info.h"
+#include "ui/events/latency_info.h"
namespace content {
diff --git a/chromium/content/browser/aura/software_output_device_win.cc b/chromium/content/browser/aura/software_output_device_win.cc
index 0332e3e936d..7937810e2ba 100644
--- a/chromium/content/browser/aura/software_output_device_win.cc
+++ b/chromium/content/browser/aura/software_output_device_win.cc
@@ -11,6 +11,7 @@
#include "ui/gfx/canvas.h"
#include "ui/gfx/canvas_skia_paint.h"
#include "ui/gfx/gdi_util.h"
+#include "ui/gfx/skia_util.h"
namespace content {
@@ -35,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, false));
+ contents_.reset(new gfx::Canvas(viewport_size, ui::SCALE_FACTOR_100P, true));
memset(&bitmap_info_, 0, sizeof(bitmap_info_));
gfx::CreateBitmapHeader(viewport_size_.width(), viewport_size_.height(),
&bitmap_info_.bmiHeader);
@@ -84,18 +85,19 @@ void SoftwareOutputDeviceWin::EndPaint(cc::SoftwareFrameData* frame_data) {
RGB(0xFF, 0xFF, 0xFF), &blend, ULW_ALPHA);
skia::EndPlatformPaint(canvas);
} else {
- SkDevice* device = canvas->getDevice();
- const SkBitmap& bitmap = device->accessBitmap(false);
HDC hdc = ::GetDC(hwnd_);
- gfx::StretchDIBits(hdc,
- rect.x(), rect.y(),
- rect.width(), rect.height(),
- rect.x(), rect.y(),
- rect.width(), rect.height(),
- bitmap.getPixels(),
- &bitmap_info_);
+ RECT src_rect = rect.ToRECT();
+ skia::DrawToNativeContext(canvas, hdc, rect.x(), rect.y(), &src_rect);
::ReleaseDC(hwnd_, hdc);
}
}
+void SoftwareOutputDeviceWin::CopyToBitmap(
+ gfx::Rect rect, SkBitmap* output) {
+ DCHECK(contents_);
+ SkBaseDevice* device = contents_->sk_canvas()->getDevice();
+ const SkBitmap& bitmap = device->accessBitmap(false);
+ bitmap.extractSubset(output, gfx::RectToSkIRect(rect));
+}
+
} // namespace content
diff --git a/chromium/content/browser/aura/software_output_device_win.h b/chromium/content/browser/aura/software_output_device_win.h
index 93568c2bd5b..9c0655b6f67 100644
--- a/chromium/content/browser/aura/software_output_device_win.h
+++ b/chromium/content/browser/aura/software_output_device_win.h
@@ -28,6 +28,7 @@ class SoftwareOutputDeviceWin : public cc::SoftwareOutputDevice {
virtual void Resize(gfx::Size viewport_size) OVERRIDE;
virtual SkCanvas* BeginPaint(gfx::Rect damage_rect) OVERRIDE;
virtual void EndPaint(cc::SoftwareFrameData* frame_data) OVERRIDE;
+ virtual void CopyToBitmap(gfx::Rect rect, SkBitmap* output) OVERRIDE;
private:
HWND hwnd_;
diff --git a/chromium/content/browser/aura/software_output_device_x11.cc b/chromium/content/browser/aura/software_output_device_x11.cc
index 229755b6ffb..abdb116ed34 100644
--- a/chromium/content/browser/aura/software_output_device_x11.cc
+++ b/chromium/content/browser/aura/software_output_device_x11.cc
@@ -16,7 +16,7 @@ namespace content {
SoftwareOutputDeviceX11::SoftwareOutputDeviceX11(ui::Compositor* compositor)
: compositor_(compositor),
- display_(ui::GetXDisplay()),
+ display_(gfx::GetXDisplay()),
gc_(NULL),
image_(NULL) {
// TODO(skaslev) Remove this when crbug.com/180702 is fixed.
diff --git a/chromium/content/browser/aura/software_output_device_x11.h b/chromium/content/browser/aura/software_output_device_x11.h
index 986a486d754..782afeee7ec 100644
--- a/chromium/content/browser/aura/software_output_device_x11.h
+++ b/chromium/content/browser/aura/software_output_device_x11.h
@@ -6,7 +6,7 @@
#define CONTENT_BROWSER_AURA_SOFTWARE_OUTPUT_DEVICE_X11_H_
#include "cc/output/software_output_device.h"
-#include "ui/base/x/x11_util.h"
+#include "ui/gfx/x/x11_types.h"
namespace ui {
class Compositor;
@@ -28,7 +28,7 @@ class SoftwareOutputDeviceX11 : public cc::SoftwareOutputDevice {
void ClearImage();
ui::Compositor* compositor_;
- Display* display_;
+ XDisplay* display_;
GC gc_;
XImage* image_;
};
diff --git a/chromium/content/browser/bookmarklet_browsertest.cc b/chromium/content/browser/bookmarklet_browsertest.cc
index 02f419302a2..35523ee63dc 100644
--- a/chromium/content/browser/bookmarklet_browsertest.cc
+++ b/chromium/content/browser/bookmarklet_browsertest.cc
@@ -6,7 +6,7 @@
#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/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/content/browser/browser_child_process_host_impl.cc b/chromium/content/browser/browser_child_process_host_impl.cc
index 780dc6a2d42..5cc953281d3 100644
--- a/chromium/content/browser/browser_child_process_host_impl.cc
+++ b/chromium/content/browser/browser_child_process_host_impl.cc
@@ -133,7 +133,7 @@ void BrowserChildProcessHostImpl::Launch(
SandboxedProcessLauncherDelegate* delegate,
#elif defined(OS_POSIX)
bool use_zygote,
- const base::EnvironmentVector& environ,
+ const base::EnvironmentMap& environ,
#endif
CommandLine* cmd_line) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
@@ -153,6 +153,9 @@ void BrowserChildProcessHostImpl::Launch(
#if defined(OS_POSIX)
switches::kChildCleanExit,
#endif
+#if defined(OS_WIN)
+ switches::kEnableHighResolutionTime,
+#endif
};
cmd_line->CopySwitchesFrom(browser_command_line, kForwardSwitches,
arraysize(kForwardSwitches));
@@ -223,11 +226,11 @@ void BrowserChildProcessHostImpl::NotifyProcessInstanceCreated(
}
base::TerminationStatus BrowserChildProcessHostImpl::GetTerminationStatus(
- int* exit_code) {
+ bool known_dead, int* exit_code) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (!child_process_) // If the delegate doesn't use Launch() helper.
return base::GetTerminationStatus(data_.handle, exit_code);
- return child_process_->GetChildTerminationStatus(false /* known_dead */,
+ return child_process_->GetChildTerminationStatus(known_dead,
exit_code);
}
@@ -264,7 +267,8 @@ void BrowserChildProcessHostImpl::OnChildDisconnected() {
if (child_process_.get() || data_.handle) {
DCHECK(data_.handle != base::kNullProcessHandle);
int exit_code;
- base::TerminationStatus status = GetTerminationStatus(&exit_code);
+ base::TerminationStatus status = GetTerminationStatus(
+ true /* known_dead */, &exit_code);
switch (status) {
case base::TERMINATION_STATUS_PROCESS_CRASHED:
case base::TERMINATION_STATUS_ABNORMAL_TERMINATION: {
diff --git a/chromium/content/browser/browser_child_process_host_impl.h b/chromium/content/browser/browser_child_process_host_impl.h
index 61971d6d978..7540209f5cc 100644
--- a/chromium/content/browser/browser_child_process_host_impl.h
+++ b/chromium/content/browser/browser_child_process_host_impl.h
@@ -46,12 +46,13 @@ class CONTENT_EXPORT BrowserChildProcessHostImpl
SandboxedProcessLauncherDelegate* delegate,
#elif defined(OS_POSIX)
bool use_zygote,
- const base::EnvironmentVector& environ,
+ const base::EnvironmentMap& environ,
#endif
CommandLine* cmd_line) OVERRIDE;
virtual const ChildProcessData& GetData() const OVERRIDE;
virtual ChildProcessHost* GetHost() const OVERRIDE;
- virtual base::TerminationStatus GetTerminationStatus(int* exit_code) OVERRIDE;
+ virtual base::TerminationStatus GetTerminationStatus(
+ bool known_dead, int* exit_code) OVERRIDE;
virtual void SetName(const string16& name) OVERRIDE;
virtual void SetHandle(base::ProcessHandle handle) OVERRIDE;
diff --git a/chromium/content/browser/browser_main_loop.cc b/chromium/content/browser/browser_main_loop.cc
index c51b5c59122..14dd61410bc 100644
--- a/chromium/content/browser/browser_main_loop.cc
+++ b/chromium/content/browser/browser_main_loop.cc
@@ -20,13 +20,15 @@
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/system_monitor/system_monitor.h"
+#include "base/thread_task_runner_handle.h"
#include "base/threading/thread_restrictions.h"
#include "base/timer/hi_res_timer_manager.h"
#include "content/browser/browser_thread_impl.h"
-#include "content/browser/device_orientation/device_motion_service.h"
+#include "content/browser/device_orientation/device_inertial_sensor_service.h"
#include "content/browser/download/save_file_manager.h"
#include "content/browser/gamepad/gamepad_service.h"
#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
+#include "content/browser/gpu/compositor_util.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/gpu/gpu_process_host_ui_shim.h"
@@ -43,7 +45,6 @@
#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/compositor_util.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_switches.h"
@@ -52,6 +53,7 @@
#include "crypto/nss_util.h"
#include "media/audio/audio_manager.h"
#include "media/base/media.h"
+#include "media/base/user_input_monitor.h"
#include "media/midi/midi_manager.h"
#include "net/base/network_change_notifier.h"
#include "net/socket/client_socket_factory.h"
@@ -64,7 +66,7 @@
#if defined(OS_ANDROID)
#include "base/android/jni_android.h"
-#include "content/browser/android/browser_startup_config.h"
+#include "content/browser/android/browser_startup_controller.h"
#include "content/browser/android/surface_texture_peer_browser_impl.h"
#endif
@@ -80,7 +82,7 @@
#include "ui/base/l10n/l10n_util_win.h"
#endif
-#if defined(OS_LINUX) || defined(OS_OPENBSD)
+#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
#include <glib-object.h>
#endif
@@ -173,7 +175,7 @@ void SetupSandbox(const CommandLine& parsed_command_line) {
}
#endif
-#if defined(OS_LINUX) || defined(OS_OPENBSD)
+#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
static void GLibLogHandler(const gchar* log_domain,
GLogLevelFlags log_level,
const gchar* message,
@@ -419,6 +421,7 @@ void BrowserMainLoop::MainMessageLoopStart() {
network_change_notifier_.reset(net::NetworkChangeNotifier::Create());
}
+#if !defined(OS_IOS)
{
TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:MediaFeatures")
media::InitializeCPUSpecificMediaFeatures();
@@ -431,8 +434,6 @@ void BrowserMainLoop::MainMessageLoopStart() {
TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:MIDIManager")
midi_manager_.reset(media::MIDIManager::Create());
}
-
-#if !defined(OS_IOS)
{
TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:ContentWebUIController")
WebUIControllerFactory::RegisterFactory(
@@ -455,6 +456,11 @@ void BrowserMainLoop::MainMessageLoopStart() {
TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:OnlineStateObserver")
online_state_observer_.reset(new BrowserOnlineStateObserver);
}
+
+ {
+ system_stats_monitor_.reset(new base::debug::TraceEventSystemStatsMonitor(
+ base::ThreadTaskRunnerHandle::Get()));
+ }
#endif // !defined(OS_IOS)
#if defined(OS_WIN)
@@ -526,36 +532,53 @@ int BrowserMainLoop::PreCreateThreads() {
}
void BrowserMainLoop::CreateStartupTasks() {
- TRACE_EVENT0("startup", "BrowserMainLoop::CreateStartupTasks")
+ TRACE_EVENT0("startup", "BrowserMainLoop::CreateStartupTasks");
+ // First time through, we really want to create all the tasks
+ if (!startup_task_runner_.get()) {
#if defined(OS_ANDROID)
- scoped_refptr<StartupTaskRunner> task_runner =
- new StartupTaskRunner(BrowserMayStartAsynchronously(),
- base::Bind(&BrowserStartupComplete),
- base::MessageLoop::current()->message_loop_proxy());
+ startup_task_runner_ = make_scoped_ptr(new StartupTaskRunner(
+ base::Bind(&BrowserStartupComplete),
+ base::MessageLoop::current()->message_loop_proxy()));
#else
- scoped_refptr<StartupTaskRunner> task_runner =
- new StartupTaskRunner(false,
- base::Callback<void(int)>(),
- base::MessageLoop::current()->message_loop_proxy());
+ startup_task_runner_ = make_scoped_ptr(new StartupTaskRunner(
+ base::Callback<void(int)>(),
+ base::MessageLoop::current()->message_loop_proxy()));
#endif
- StartupTask pre_create_threads =
- base::Bind(&BrowserMainLoop::PreCreateThreads, base::Unretained(this));
- task_runner->AddTask(pre_create_threads);
+ StartupTask pre_create_threads =
+ base::Bind(&BrowserMainLoop::PreCreateThreads, base::Unretained(this));
+ startup_task_runner_->AddTask(pre_create_threads);
- StartupTask create_threads =
- base::Bind(&BrowserMainLoop::CreateThreads, base::Unretained(this));
- task_runner->AddTask(create_threads);
+ StartupTask create_threads =
+ base::Bind(&BrowserMainLoop::CreateThreads, base::Unretained(this));
+ startup_task_runner_->AddTask(create_threads);
- StartupTask browser_thread_started = base::Bind(
- &BrowserMainLoop::BrowserThreadsStarted, base::Unretained(this));
- task_runner->AddTask(browser_thread_started);
+ StartupTask browser_thread_started = base::Bind(
+ &BrowserMainLoop::BrowserThreadsStarted, base::Unretained(this));
+ startup_task_runner_->AddTask(browser_thread_started);
- StartupTask pre_main_message_loop_run = base::Bind(
- &BrowserMainLoop::PreMainMessageLoopRun, base::Unretained(this));
- task_runner->AddTask(pre_main_message_loop_run);
+ StartupTask pre_main_message_loop_run = base::Bind(
+ &BrowserMainLoop::PreMainMessageLoopRun, base::Unretained(this));
+ startup_task_runner_->AddTask(pre_main_message_loop_run);
- task_runner->StartRunningTasks();
+#if defined(OS_ANDROID)
+ if (BrowserMayStartAsynchronously()) {
+ startup_task_runner_->StartRunningTasksAsync();
+ }
+#endif
+ }
+#if defined(OS_ANDROID)
+ if (!BrowserMayStartAsynchronously()) {
+ // A second request for asynchronous startup can be ignored, so
+ // StartupRunningTasksAsync is only called first time through. If, however,
+ // this is a request for synchronous startup then it must override any
+ // previous call for async startup, so we call RunAllTasksNow()
+ // unconditionally.
+ startup_task_runner_->RunAllTasksNow();
+ }
+#else
+ startup_task_runner_->RunAllTasksNow();
+#endif
}
int BrowserMainLoop::CreateThreads() {
@@ -681,6 +704,8 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
// Called early, nothing to do
return;
}
+ TRACE_EVENT0("shutdown", "BrowserMainLoop::ShutdownThreadsAndCleanUp")
+
// Teardown may start in PostMainMessageLoopRun, and during teardown we
// need to be able to perform IO.
base::ThreadRestrictions::SetIOAllowed(true);
@@ -689,24 +714,37 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
base::Bind(base::IgnoreResult(&base::ThreadRestrictions::SetIOAllowed),
true));
- if (parts_)
+ if (parts_) {
+ TRACE_EVENT0("shutdown",
+ "BrowserMainLoop::Subsystem:PostMainMessageLoopRun");
parts_->PostMainMessageLoopRun();
+ }
trace_memory_controller_.reset();
+ system_stats_monitor_.reset();
#if !defined(OS_IOS)
// Destroying the GpuProcessHostUIShims on the UI thread posts a task to
// delete related objects on the GPU thread. This must be done before
// stopping the GPU thread. The GPU thread will close IPC channels to renderer
// processes so this has to happen before stopping the IO thread.
- GpuProcessHostUIShim::DestroyAll();
-
+ {
+ TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:GPUProcessHostShim");
+ GpuProcessHostUIShim::DestroyAll();
+ }
// Cancel pending requests and prevent new requests.
- if (resource_dispatcher_host_)
+ if (resource_dispatcher_host_) {
+ TRACE_EVENT0("shutdown",
+ "BrowserMainLoop::Subsystem:ResourceDispatcherHost");
resource_dispatcher_host_.get()->Shutdown();
+ }
#if defined(USE_AURA)
- ImageTransportFactory::Terminate();
+ {
+ TRACE_EVENT0("shutdown",
+ "BrowserMainLoop::Subsystem:ImageTransportFactory");
+ ImageTransportFactory::Terminate();
+ }
#endif
// The device monitors are using |system_monitor_| as dependency, so delete
@@ -743,29 +781,42 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
//
// - (Not sure why DB stops last.)
switch (thread_id) {
- case BrowserThread::DB:
- db_thread_.reset();
+ case BrowserThread::DB: {
+ TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:DBThread");
+ db_thread_.reset();
+ }
break;
- case BrowserThread::FILE_USER_BLOCKING:
- file_user_blocking_thread_.reset();
+ case BrowserThread::FILE_USER_BLOCKING: {
+ TRACE_EVENT0("shutdown",
+ "BrowserMainLoop::Subsystem:FileUserBlockingThread");
+ file_user_blocking_thread_.reset();
+ }
break;
- case BrowserThread::FILE:
+ case BrowserThread::FILE: {
+ TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:FileThread");
#if !defined(OS_IOS)
- // Clean up state that lives on or uses the file_thread_ before
- // it goes away.
- if (resource_dispatcher_host_)
- resource_dispatcher_host_.get()->save_file_manager()->Shutdown();
+ // Clean up state that lives on or uses the file_thread_ before
+ // it goes away.
+ if (resource_dispatcher_host_)
+ resource_dispatcher_host_.get()->save_file_manager()->Shutdown();
#endif // !defined(OS_IOS)
- file_thread_.reset();
+ file_thread_.reset();
+ }
break;
- case BrowserThread::PROCESS_LAUNCHER:
- process_launcher_thread_.reset();
+ case BrowserThread::PROCESS_LAUNCHER: {
+ TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:LauncherThread");
+ process_launcher_thread_.reset();
+ }
break;
- case BrowserThread::CACHE:
- cache_thread_.reset();
+ case BrowserThread::CACHE: {
+ TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:CacheThread");
+ cache_thread_.reset();
+ }
break;
- case BrowserThread::IO:
- io_thread_.reset();
+ case BrowserThread::IO: {
+ TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:IOThread");
+ io_thread_.reset();
+ }
break;
case BrowserThread::UI:
case BrowserThread::ID_COUNT:
@@ -776,7 +827,10 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
}
#if !defined(OS_IOS)
- indexed_db_thread_.reset();
+ {
+ TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:IndexedDBThread");
+ indexed_db_thread_.reset();
+ }
#endif
// Close the blocking I/O pool after the other threads. Other threads such
@@ -785,23 +839,39 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
// may also be slow operations pending that will blcok shutdown, so closing
// it here (which will block until required operations are complete) gives
// more head start for those operations to finish.
- BrowserThreadImpl::ShutdownThreadPool();
+ {
+ TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:ThreadPool");
+ BrowserThreadImpl::ShutdownThreadPool();
+ }
#if !defined(OS_IOS)
// Must happen after the IO thread is shutdown since this may be accessed from
// it.
- BrowserGpuChannelHostFactory::Terminate();
+ {
+ TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:GPUChannelFactory");
+ BrowserGpuChannelHostFactory::Terminate();
+ }
// Must happen after the I/O thread is shutdown since this class lives on the
// I/O thread and isn't threadsafe.
- GamepadService::GetInstance()->Terminate();
- DeviceMotionService::GetInstance()->Shutdown();
-
- URLDataManager::DeleteDataSources();
+ {
+ TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:GamepadService");
+ GamepadService::GetInstance()->Terminate();
+ }
+ {
+ TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:SensorService");
+ DeviceInertialSensorService::GetInstance()->Shutdown();
+ }
+ {
+ TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:DeleteDataSources");
+ URLDataManager::DeleteDataSources();
+ }
#endif // !defined(OS_IOS)
- if (parts_)
+ if (parts_) {
+ TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:PostDestroyThreads");
parts_->PostDestroyThreads();
+ }
}
void BrowserMainLoop::InitializeMainThread() {
@@ -872,6 +942,14 @@ int BrowserMainLoop::BrowserThreadsStarted() {
audio_manager_.get(), media_stream_manager_.get()));
}
+ {
+ TRACE_EVENT0(
+ "startup",
+ "BrowserMainLoop::BrowserThreadsStarted::InitUserInputMonitor");
+ user_input_monitor_ = media::UserInputMonitor::Create(
+ io_thread_->message_loop_proxy(), main_thread_->message_loop_proxy());
+ }
+
// Alert the clipboard class to which threads are allowed to access the
// clipboard:
std::vector<base::PlatformThreadId> allowed_clipboard_threads;
@@ -887,8 +965,13 @@ 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) &&
- IsForceCompositingModeEnabled() &&
+ always_uses_gpu &&
!parsed_command_line_.HasSwitch(switches::kDisableGpuProcessPrelaunch) &&
!parsed_command_line_.HasSwitch(switches::kSingleProcess) &&
!parsed_command_line_.HasSwitch(switches::kInProcessGPU)) {
@@ -911,7 +994,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_LINUX) || defined(OS_OPENBSD)
+#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
diff --git a/chromium/content/browser/browser_main_loop.h b/chromium/content/browser/browser_main_loop.h
index 7b2879f70e4..821da872755 100644
--- a/chromium/content/browser/browser_main_loop.h
+++ b/chromium/content/browser/browser_main_loop.h
@@ -20,12 +20,14 @@ class PowerMonitor;
class SystemMonitor;
namespace debug {
class TraceMemoryController;
+class TraceEventSystemStatsMonitor;
} // namespace debug
} // namespace base
namespace media {
class AudioManager;
class MIDIManager;
+class UserInputMonitor;
} // namespace media
namespace net {
@@ -41,6 +43,7 @@ class BrowserThreadImpl;
class MediaStreamManager;
class ResourceDispatcherHostImpl;
class SpeechRecognitionManagerImpl;
+class StartupTaskRunner;
class SystemMessageWindowWin;
struct MainFunctionParams;
@@ -67,7 +70,10 @@ class CONTENT_EXPORT BrowserMainLoop {
void InitializeToolkit();
void MainMessageLoopStart();
- // Create the tasks we need to complete startup.
+ // Create and start running the tasks we need to complete startup. Note that
+ // this can be called more than once (currently only on Android) if we get a
+ // request for synchronous startup while the tasks created by asynchronous
+ // startup are still running.
void CreateStartupTasks();
// Perform the default message loop run logic.
@@ -86,6 +92,9 @@ class CONTENT_EXPORT BrowserMainLoop {
MediaStreamManager* media_stream_manager() const {
return media_stream_manager_.get();
}
+ media::UserInputMonitor* user_input_monitor() const {
+ return user_input_monitor_.get();
+ }
media::MIDIManager* midi_manager() const { return midi_manager_.get(); }
base::Thread* indexed_db_thread() const { return indexed_db_thread_.get(); }
@@ -122,6 +131,8 @@ class CONTENT_EXPORT BrowserMainLoop {
scoped_ptr<base::PowerMonitor> power_monitor_;
scoped_ptr<base::HighResolutionTimerManager> hi_res_timer_manager_;
scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_;
+ // user_input_monitor_ has to outlive audio_manager_, so declared first.
+ scoped_ptr<media::UserInputMonitor> user_input_monitor_;
scoped_ptr<media::AudioManager> audio_manager_;
scoped_ptr<media::MIDIManager> midi_manager_;
scoped_ptr<AudioMirroringManager> audio_mirroring_manager_;
@@ -135,6 +146,8 @@ class CONTENT_EXPORT BrowserMainLoop {
#elif defined(OS_MACOSX) && !defined(OS_IOS)
scoped_ptr<DeviceMonitorMac> device_monitor_mac_;
#endif
+ // The startup task runner is created by CreateStartupTasks()
+ scoped_ptr<StartupTaskRunner> startup_task_runner_;
// Destroy parts_ before main_message_loop_ (required) and before other
// classes constructed in content (but after main_thread_).
@@ -158,6 +171,7 @@ class CONTENT_EXPORT BrowserMainLoop {
scoped_ptr<base::Thread> indexed_db_thread_;
scoped_ptr<MemoryObserver> memory_observer_;
scoped_ptr<base::debug::TraceMemoryController> trace_memory_controller_;
+ scoped_ptr<base::debug::TraceEventSystemStatsMonitor> system_stats_monitor_;
DISALLOW_COPY_AND_ASSIGN(BrowserMainLoop);
};
diff --git a/chromium/content/browser/browser_main_runner.cc b/chromium/content/browser/browser_main_runner.cc
index cca1466d9bb..27fb6fcff58 100644
--- a/chromium/content/browser/browser_main_runner.cc
+++ b/chromium/content/browser/browser_main_runner.cc
@@ -12,6 +12,7 @@
#include "base/metrics/histogram.h"
#include "base/metrics/statistics_recorder.h"
#include "content/browser/browser_main_loop.h"
+#include "content/browser/browser_shutdown_profile_dumper.h"
#include "content/browser/notification_service_impl.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/main_function_params.h"
@@ -29,75 +30,82 @@ namespace content {
class BrowserMainRunnerImpl : public BrowserMainRunner {
public:
- BrowserMainRunnerImpl() : is_initialized_(false), is_shutdown_(false) {}
+ BrowserMainRunnerImpl()
+ : initialization_started_(false), is_shutdown_(false) {}
virtual ~BrowserMainRunnerImpl() {
- if (is_initialized_ && !is_shutdown_)
+ if (initialization_started_ && !is_shutdown_)
Shutdown();
}
- virtual int Initialize(const MainFunctionParams& parameters)
- OVERRIDE {
- TRACE_EVENT0("startup", "BrowserMainRunnerImpl::Initialize")
- is_initialized_ = true;
+ virtual int Initialize(const MainFunctionParams& parameters) OVERRIDE {
+ TRACE_EVENT0("startup", "BrowserMainRunnerImpl::Initialize");
+ // On Android we normally initialize the browser in a series of UI thread
+ // tasks. While this is happening a second request can come from the OS or
+ // another application to start the browser. If this happens then we must
+ // not run these parts of initialization twice.
+ if (!initialization_started_) {
+ initialization_started_ = true;
#if !defined(OS_IOS)
- if (parameters.command_line.HasSwitch(switches::kWaitForDebugger))
- base::debug::WaitForDebugger(60, true);
+ if (parameters.command_line.HasSwitch(switches::kWaitForDebugger))
+ base::debug::WaitForDebugger(60, true);
#endif
#if defined(OS_WIN)
- if (parameters.command_line.HasSwitch(
- switches::kEnableTextServicesFramework)) {
- base::win::SetForceToUseTSF();
- } else if (base::win::GetVersion() < base::win::VERSION_VISTA) {
- // When "Extend support of advanced text services to all programs"
- // (a.k.a. Cicero Unaware Application Support; CUAS) is enabled on
- // Windows XP and handwriting modules shipped with Office 2003 are
- // installed, "penjpn.dll" and "skchui.dll" will be loaded and then crash
- // unless a user installs Office 2003 SP3. To prevent these modules from
- // being loaded, disable TSF entirely. crbug/160914.
- // TODO(yukawa): Add a high-level wrapper for this instead of calling
- // Win32 API here directly.
- ImmDisableTextFrameService(static_cast<DWORD>(-1));
- }
+ if (parameters.command_line.HasSwitch(
+ switches::kEnableTextServicesFramework)) {
+ base::win::SetForceToUseTSF();
+ } else if (base::win::GetVersion() < base::win::VERSION_VISTA) {
+ // When "Extend support of advanced text services to all programs"
+ // (a.k.a. Cicero Unaware Application Support; CUAS) is enabled on
+ // Windows XP and handwriting modules shipped with Office 2003 are
+ // installed, "penjpn.dll" and "skchui.dll" will be loaded and then
+ // crash
+ // unless a user installs Office 2003 SP3. To prevent these modules from
+ // being loaded, disable TSF entirely. crbug/160914.
+ // TODO(yukawa): Add a high-level wrapper for this instead of calling
+ // Win32 API here directly.
+ ImmDisableTextFrameService(static_cast<DWORD>(-1));
+ }
#endif // OS_WIN
- base::StatisticsRecorder::Initialize();
+ base::StatisticsRecorder::Initialize();
- notification_service_.reset(new NotificationServiceImpl);
+ notification_service_.reset(new NotificationServiceImpl);
#if defined(OS_WIN)
- // Ole must be initialized before starting message pump, so that TSF
- // (Text Services Framework) module can interact with the message pump
- // on Windows 8 Metro mode.
- ole_initializer_.reset(new ui::ScopedOleInitializer);
+ // Ole must be initialized before starting message pump, so that TSF
+ // (Text Services Framework) module can interact with the message pump
+ // on Windows 8 Metro mode.
+ ole_initializer_.reset(new ui::ScopedOleInitializer);
#endif // OS_WIN
- main_loop_.reset(new BrowserMainLoop(parameters));
+ main_loop_.reset(new BrowserMainLoop(parameters));
- main_loop_->Init();
+ main_loop_->Init();
- main_loop_->EarlyInitialization();
+ main_loop_->EarlyInitialization();
- // Must happen before we try to use a message loop or display any UI.
- main_loop_->InitializeToolkit();
+ // Must happen before we try to use a message loop or display any UI.
+ main_loop_->InitializeToolkit();
- main_loop_->MainMessageLoopStart();
+ main_loop_->MainMessageLoopStart();
- // WARNING: If we get a WM_ENDSESSION, objects created on the stack here
- // are NOT deleted. If you need something to run during WM_ENDSESSION add it
- // to browser_shutdown::Shutdown or BrowserProcess::EndSession.
+// WARNING: If we get a WM_ENDSESSION, objects created on the stack here
+// are NOT deleted. If you need something to run during WM_ENDSESSION add it
+// to browser_shutdown::Shutdown or BrowserProcess::EndSession.
#if defined(OS_WIN) && !defined(NO_TCMALLOC)
- // When linking shared libraries, NO_TCMALLOC is defined, and dynamic
- // allocator selection is not supported.
+ // When linking shared libraries, NO_TCMALLOC is defined, and dynamic
+ // allocator selection is not supported.
- // Make this call before going multithreaded, or spawning any subprocesses.
- base::allocator::SetupSubprocessAllocator();
+ // Make this call before going multithreaded, or spawning any
+ // subprocesses.
+ base::allocator::SetupSubprocessAllocator();
#endif
- ui::InitializeInputMethod();
-
+ ui::InitializeInputMethod();
+ }
main_loop_->CreateStartupTasks();
int result_code = main_loop_->GetResultCode();
if (result_code > 0)
@@ -108,34 +116,46 @@ class BrowserMainRunnerImpl : public BrowserMainRunner {
}
virtual int Run() OVERRIDE {
- DCHECK(is_initialized_);
+ DCHECK(initialization_started_);
DCHECK(!is_shutdown_);
main_loop_->RunMainMessageLoopParts();
return main_loop_->GetResultCode();
}
virtual void Shutdown() OVERRIDE {
- DCHECK(is_initialized_);
+ DCHECK(initialization_started_);
DCHECK(!is_shutdown_);
- g_exited_main_message_loop = true;
+ // 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.
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ scoped_ptr<BrowserShutdownProfileDumper> profiler;
+ if (command_line.HasSwitch(switches::kTraceShutdown))
+ profiler.reset(new BrowserShutdownProfileDumper());
- main_loop_->ShutdownThreadsAndCleanUp();
+ {
+ // The trace event has to stay between profiler creation and destruction.
+ TRACE_EVENT0("shutdown", "BrowserMainRunner");
+ g_exited_main_message_loop = true;
- ui::ShutdownInputMethod();
-#if defined(OS_WIN)
- ole_initializer_.reset(NULL);
-#endif
+ main_loop_->ShutdownThreadsAndCleanUp();
+
+ ui::ShutdownInputMethod();
+ #if defined(OS_WIN)
+ ole_initializer_.reset(NULL);
+ #endif
- main_loop_.reset(NULL);
+ main_loop_.reset(NULL);
- notification_service_.reset(NULL);
+ notification_service_.reset(NULL);
- is_shutdown_ = true;
+ is_shutdown_ = true;
+ }
}
protected:
- // True if the runner has been initialized.
- bool is_initialized_;
+ // True if we have started to initialize the runner.
+ bool initialization_started_;
// True if the runner has been shut down.
bool is_shutdown_;
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_embedder.cc b/chromium/content/browser/browser_plugin/browser_plugin_embedder.cc
index 4a06aca32c9..1f673ba520f 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_embedder.cc
+++ b/chromium/content/browser/browser_plugin/browser_plugin_embedder.cc
@@ -188,7 +188,8 @@ void BrowserPluginEmbedder::OnAttach(
guest->GetWebContents(),
web_contents(),
extra_params);
- guest->Attach(static_cast<WebContentsImpl*>(web_contents()), params);
+ guest->Attach(
+ static_cast<WebContentsImpl*>(web_contents()), params, extra_params);
return;
}
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest.cc b/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
index 5f1ec69e8af..19e7eba3d44 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -6,7 +6,6 @@
#include <algorithm>
-#include "base/command_line.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -15,6 +14,7 @@
#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"
+#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
@@ -38,13 +38,14 @@
#include "content/public/browser/resource_request_details.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_contents_view.h"
-#include "content/public/common/content_switches.h"
#include "content/public/common/drop_data.h"
#include "content/public/common/media_stream_request.h"
#include "content/public/common/result_codes.h"
+#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 "ui/base/keycodes/keyboard_codes.h"
+#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/surface/transport_dib.h"
#include "webkit/common/resource_type.h"
@@ -127,7 +128,7 @@ class BrowserPluginGuest::GeolocationRequest : public PermissionRequest {
// in the fact whether the embedder/app has geolocation
// permission. Therefore we use an invalid |bridge_id|.
-1 /* bridge_id */,
- web_contents->GetURL(),
+ web_contents->GetLastCommittedURL(),
geolocation_callback);
return;
}
@@ -317,8 +318,7 @@ class BrowserPluginGuest::EmbedderRenderViewHostObserver
// RenderViewHostObserver:
virtual void RenderViewHostDestroyed(
RenderViewHost* render_view_host) OVERRIDE {
- browser_plugin_guest_->embedder_web_contents_ = NULL;
- browser_plugin_guest_->Destroy();
+ browser_plugin_guest_->EmbedderDestroyed();
}
private:
@@ -348,6 +348,7 @@ BrowserPluginGuest::BrowserPluginGuest(
embedder_visible_(true),
next_permission_request_id_(browser_plugin::kInvalidPermissionRequestID),
has_render_view_(has_render_view),
+ last_seen_auto_size_enabled_(false),
is_in_destruction_(false) {
DCHECK(web_contents);
web_contents->SetDelegate(this);
@@ -421,6 +422,54 @@ int BrowserPluginGuest::RequestPermission(
return request_id;
}
+BrowserPluginGuest* BrowserPluginGuest::CreateNewGuestWindow(
+ const OpenURLParams& params) {
+ BrowserPluginGuestManager* guest_manager =
+ GetWebContents()->GetBrowserPluginGuestManager();
+
+ // Allocate a new instance ID for the new guest.
+ int instance_id = guest_manager->get_next_instance_id();
+
+ // Set the attach params to use the same partition as the opener.
+ // We pull the partition information from the site's URL, which is of the form
+ // guest://site/{persist}?{partition_name}.
+ const GURL& site_url = GetWebContents()->GetSiteInstance()->GetSiteURL();
+ BrowserPluginHostMsg_Attach_Params attach_params;
+ attach_params.storage_partition_id = site_url.query();
+ attach_params.persist_storage =
+ site_url.path().find("persist") != std::string::npos;
+
+ // The new guest gets a copy of this guest's extra params so that the content
+ // embedder exposes the same API for this guest as its opener.
+ scoped_ptr<base::DictionaryValue> extra_params(
+ extra_attach_params_->DeepCopy());
+ BrowserPluginGuest* new_guest =
+ GetWebContents()->GetBrowserPluginGuestManager()->CreateGuest(
+ GetWebContents()->GetSiteInstance(), instance_id,
+ attach_params, extra_params.Pass());
+ new_guest->opener_ = AsWeakPtr();
+
+ // Take ownership of |new_guest|.
+ pending_new_windows_.insert(
+ 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);
+
+ return new_guest;
+}
+
+void BrowserPluginGuest::EmbedderDestroyed() {
+ embedder_web_contents_ = NULL;
+ if (delegate_)
+ delegate_->EmbedderDestroyed();
+ Destroy();
+}
+
void BrowserPluginGuest::Destroy() {
is_in_destruction_ = true;
if (!attached() && opener())
@@ -503,6 +552,8 @@ void BrowserPluginGuest::Initialize(
// Navigation is disabled in Chrome Apps. We want to make sure guest-initiated
// navigations still continue to function inside the app.
renderer_prefs->browser_handles_all_top_level_requests = false;
+ // 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
@@ -543,6 +594,18 @@ void BrowserPluginGuest::Initialize(
GetWebContents()->GetRenderViewHost());
guest_rvh->SetInputMethodActive(true);
}
+
+ // Inform the embedder of the guest's information.
+ // We pull the partition information from the site's URL, which is of the form
+ // guest://site/{persist}?{partition_name}.
+ const GURL& site_url = GetWebContents()->GetSiteInstance()->GetSiteURL();
+ BrowserPluginMsg_Attach_ACK_Params ack_params;
+ ack_params.storage_partition_id = site_url.query();
+ ack_params.persist_storage =
+ site_url.path().find("persist") != std::string::npos;
+ ack_params.name = name_;
+ SendMessageToEmbedder(
+ new BrowserPluginMsg_Attach_ACK(instance_id_, ack_params));
}
BrowserPluginGuest::~BrowserPluginGuest() {
@@ -564,6 +627,7 @@ BrowserPluginGuest* BrowserPluginGuest::Create(
} else {
guest = new BrowserPluginGuest(instance_id, web_contents, NULL, false);
}
+ guest->extra_attach_params_.reset(extra_params->DeepCopy());
web_contents->SetBrowserPluginGuest(guest);
BrowserPluginGuestDelegate* delegate = NULL;
GetContentClient()->browser()->GuestWebContentsCreated(
@@ -654,6 +718,12 @@ void BrowserPluginGuest::CanDownload(
callback));
}
+void BrowserPluginGuest::LoadProgressChanged(WebContents* contents,
+ double progress) {
+ if (delegate_)
+ delegate_->LoadProgressed(progress);
+}
+
void BrowserPluginGuest::CloseContents(WebContents* source) {
if (!delegate_)
return;
@@ -711,10 +781,14 @@ WebContents* BrowserPluginGuest::OpenURLFromTab(WebContents* source,
it->second = new_window_info;
return NULL;
}
- // This can happen for cross-site redirects.
- source->GetController().LoadURL(
- params.url, params.referrer, params.transition, std::string());
- return source;
+ if (params.disposition == CURRENT_TAB) {
+ // This can happen for cross-site redirects.
+ source->GetController().LoadURL(
+ params.url, params.referrer, params.transition, std::string());
+ return source;
+ }
+
+ return CreateNewGuestWindow(params)->GetWebContents();
}
void BrowserPluginGuest::WebContentsCreated(WebContents* source_contents,
@@ -766,6 +840,10 @@ WebContentsImpl* BrowserPluginGuest::GetWebContents() {
base::SharedMemory* BrowserPluginGuest::GetDamageBufferFromEmbedder(
const BrowserPluginHostMsg_ResizeGuest_Params& params) {
+ if (!attached()) {
+ LOG(WARNING) << "Attempting to map a damage buffer prior to attachment.";
+ return NULL;
+ }
#if defined(OS_WIN)
base::ProcessHandle handle =
embedder_web_contents_->GetRenderProcessHost()->GetHandle();
@@ -961,9 +1039,8 @@ void BrowserPluginGuest::DidCommitProvisionalLoadForFrame(
}
void BrowserPluginGuest::DidStopLoading(RenderViewHost* render_view_host) {
- bool disable_dragdrop = !CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBrowserPluginDragDrop);
- if (disable_dragdrop) {
+ bool enable_dragdrop = delegate_ && delegate_->IsDragAndDropEnabled();
+ if (!enable_dragdrop) {
// Initiating a drag from inside a guest is currently not supported without
// the kEnableBrowserPluginDragDrop flag on a linux platform. So inject some
// JS to disable it. http://crbug.com/161112
@@ -1080,10 +1157,13 @@ bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message) {
void BrowserPluginGuest::Attach(
WebContentsImpl* embedder_web_contents,
- BrowserPluginHostMsg_Attach_Params params) {
+ BrowserPluginHostMsg_Attach_Params params,
+ const base::DictionaryValue& extra_params) {
if (attached())
return;
+ extra_attach_params_.reset(extra_params.DeepCopy());
+
// Clear parameters that get inherited from the opener.
params.storage_partition_id.clear();
params.persist_storage = false;
@@ -1125,18 +1205,6 @@ void BrowserPluginGuest::Attach(
Initialize(embedder_web_contents, params);
- // Inform the embedder of the guest's information.
- // We pull the partition information from the site's URL, which is of the form
- // guest://site/{persist}?{partition_name}.
- const GURL& site_url = GetWebContents()->GetSiteInstance()->GetSiteURL();
- BrowserPluginMsg_Attach_ACK_Params ack_params;
- ack_params.storage_partition_id = site_url.query();
- ack_params.persist_storage =
- site_url.path().find("persist") != std::string::npos;
- ack_params.name = name_;
- SendMessageToEmbedder(
- new BrowserPluginMsg_Attach_ACK(instance_id_, ack_params));
-
SendQueuedMessages();
RecordAction(UserMetricsAction("BrowserPlugin.Guest.Attached"));
@@ -1261,7 +1329,7 @@ void BrowserPluginGuest::OnLockMouse(bool user_gesture,
base::Value::CreateBooleanValue(last_unlocked_by_target));
request_info.Set(browser_plugin::kURL,
base::Value::CreateStringValue(
- web_contents()->GetURL().spec()));
+ web_contents()->GetLastCommittedURL().spec()));
RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_POINTER_LOCK,
new PointerLockRequest(this),
@@ -1285,13 +1353,31 @@ void BrowserPluginGuest::OnNavigateGuest(
// 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;
+ }
+
// 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());
+ PAGE_TRANSITION_AUTO_TOPLEVEL,
+ std::string());
}
}
@@ -1318,6 +1404,13 @@ void BrowserPluginGuest::OnResizeGuest(
render_widget_host->NotifyScreenInfoChanged();
}
}
+ // When autosize is turned off and as a result there is a layout change, we
+ // send a sizechanged event.
+ if (!auto_size_enabled_ && last_seen_auto_size_enabled_ &&
+ !params.view_rect.size().IsEmpty() && delegate_) {
+ delegate_->SizeChanged(last_seen_view_size_, params.view_rect.size());
+ last_seen_auto_size_enabled_ = false;
+ }
// 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)) {
@@ -1362,6 +1455,7 @@ void BrowserPluginGuest::OnSetSize(
if (auto_size_enabled_ && (!old_auto_size_enabled ||
(old_max_size != max_auto_size_) ||
(old_min_size != min_auto_size_))) {
+ RecordAction(UserMetricsAction("BrowserPlugin.Guest.EnableAutoResize"));
GetWebContents()->GetRenderViewHost()->EnableAutoResize(
min_auto_size_, max_auto_size_);
// TODO(fsamuel): If we're changing autosize parameters, then we force
@@ -1580,6 +1674,16 @@ void BrowserPluginGuest::OnUpdateRect(
params.flags);
relay_params.needs_ack = params.needs_ack;
+ bool size_changed = last_seen_view_size_ != params.view_size;
+ gfx::Size old_size = last_seen_view_size_;
+ last_seen_view_size_ = params.view_size;
+
+ if ((auto_size_enabled_ || last_seen_auto_size_enabled_) &&
+ size_changed && delegate_) {
+ delegate_->SizeChanged(old_size, last_seen_view_size_);
+ }
+ last_seen_auto_size_enabled_ = auto_size_enabled_;
+
// HW accelerated case, acknowledge resize only
if (!params.needs_ack || !damage_buffer_) {
relay_params.damage_buffer_sequence_id = 0;
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest.h b/chromium/content/browser/browser_plugin/browser_plugin_guest.h
index 6098cacca38..0101ff7118d 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_guest.h
+++ b/chromium/content/browser/browser_plugin/browser_plugin_guest.h
@@ -104,6 +104,10 @@ class CONTENT_EXPORT BrowserPluginGuest
BrowserPluginGuest* opener,
bool has_render_view);
+ // Called when the embedder RenderViewHost is destroyed to give the
+ // BrowserPluginGuest an opportunity to clean up after itself.
+ void EmbedderDestroyed();
+
// Destroys the guest WebContents and all its associated state, including
// this BrowserPluginGuest, and its new unattached windows.
void Destroy();
@@ -182,6 +186,8 @@ class CONTENT_EXPORT BrowserPluginGuest
int request_id,
const std::string& request_method,
const base::Callback<void(bool)>& callback) OVERRIDE;
+ virtual void LoadProgressChanged(WebContents* source,
+ double progress) OVERRIDE;
virtual void CloseContents(WebContents* source) OVERRIDE;
virtual JavaScriptDialogManager* GetJavaScriptDialogManager() OVERRIDE;
virtual bool HandleContextMenu(const ContextMenuParams& params) OVERRIDE;
@@ -248,9 +254,12 @@ class CONTENT_EXPORT BrowserPluginGuest
// Attaches this BrowserPluginGuest to the provided |embedder_web_contents|
// and initializes the guest with the provided |params|. Attaching a guest
// to an embedder implies that this guest's lifetime is no longer managed
- // by its opener, and it can begin loading resources.
+ // by its opener, and it can begin loading resources. |extra_params| are
+ // parameters passed into BrowserPlugin from JavaScript to be forwarded to
+ // the content embedder.
void Attach(WebContentsImpl* embedder_web_contents,
- BrowserPluginHostMsg_Attach_Params params);
+ BrowserPluginHostMsg_Attach_Params params,
+ const base::DictionaryValue& extra_params);
// Requests geolocation permission through Embedder JavaScript API.
void AskEmbedderForGeolocationPermission(int bridge_id,
@@ -320,6 +329,10 @@ class CONTENT_EXPORT BrowserPluginGuest
scoped_refptr<BrowserPluginGuest::PermissionRequest> request,
const base::DictionaryValue& request_info);
+ // Creates a new guest window, and BrowserPluginGuest that is owned by this
+ // BrowserPluginGuest.
+ BrowserPluginGuest* CreateNewGuestWindow(const OpenURLParams& params);
+
base::SharedMemory* damage_buffer() const { return damage_buffer_.get(); }
const gfx::Size& damage_view_size() const { return damage_view_size_; }
float damage_buffer_scale_factor() const {
@@ -516,6 +529,11 @@ class CONTENT_EXPORT BrowserPluginGuest
// this guest is attached.
bool has_render_view_;
+ // Last seen size of guest contents (by OnUpdateRect).
+ gfx::Size last_seen_view_size_;
+ // Last seen autosize attribute state (by OnUpdateRect).
+ bool last_seen_auto_size_enabled_;
+
bool is_in_destruction_;
// This is a queue of messages that are destined to be sent to the embedder
@@ -524,6 +542,10 @@ class CONTENT_EXPORT BrowserPluginGuest
scoped_ptr<BrowserPluginGuestDelegate> delegate_;
+ // These are parameters passed from JavaScript on attachment to the content
+ // embedder.
+ scoped_ptr<base::DictionaryValue> extra_attach_params_;
+
DISALLOW_COPY_AND_ASSIGN(BrowserPluginGuest);
};
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 75de2031333..6c86331b0fe 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_guest_manager.cc
+++ b/chromium/content/browser/browser_plugin/browser_plugin_guest_manager.cc
@@ -17,7 +17,7 @@
#include "content/public/common/result_codes.h"
#include "content/public/common/url_constants.h"
#include "net/base/escape.h"
-#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/events/keycodes/keyboard_codes.h"
namespace content {
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 4fc2ae80335..d49f169f05f 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_host_browsertest.cc
+++ b/chromium/content/browser/browser_plugin/browser_plugin_host_browsertest.cc
@@ -13,6 +13,7 @@
#include "content/browser/browser_plugin/browser_plugin_host_factory.h"
#include "content/browser/browser_plugin/test_browser_plugin_embedder.h"
#include "content/browser/browser_plugin/test_browser_plugin_guest.h"
+#include "content/browser/browser_plugin/test_browser_plugin_guest_delegate.h"
#include "content/browser/browser_plugin/test_browser_plugin_guest_manager.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
@@ -24,9 +25,10 @@
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/drop_data.h"
+#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_utils.h"
-#include "content/shell/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
#include "net/base/net_util.h"
@@ -251,6 +253,9 @@ class BrowserPluginHostTest : public ContentBrowserTest {
#if defined(OS_WIN) && !defined(USE_AURA)
UseRealGLBindings();
#endif
+ // We need real contexts, otherwise the embedder doesn't composite, but the
+ // guest does, and that isn't an expected configuration.
+ UseRealGLContexts();
ContentBrowserTest::SetUp();
}
@@ -763,86 +768,12 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, FocusBeforeNavigation) {
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, FocusTracksEmbedder) {
const char* kEmbedderURL = "/browser_plugin_embedder.html";
StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, std::string());
- RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
- test_embedder()->web_contents()->GetRenderViewHost());
- RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
- test_guest()->web_contents()->GetRenderViewHost());
- {
- // Focus the BrowserPlugin. This will have the effect of also focusing the
- // current guest.
- ExecuteSyncJSFunction(rvh, "document.getElementById('plugin').focus();");
- // Verify that key presses go to the guest.
- SimulateSpaceKeyPress(test_embedder()->web_contents());
- test_guest()->WaitForInput();
- // Verify that the guest is focused.
- scoped_ptr<base::Value> value =
- content::ExecuteScriptAndGetValue(guest_rvh, "document.hasFocus()");
- bool result = false;
- ASSERT_TRUE(value->GetAsBoolean(&result));
- EXPECT_TRUE(result);
- }
// Blur the embedder.
test_embedder()->web_contents()->GetRenderViewHost()->Blur();
+ // Ensure that the guest is also blurred.
test_guest()->WaitForBlur();
}
-// This test verifies that if a browser plugin is in autosize mode before
-// navigation then the guest starts auto-sized.
-IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, AutoSizeBeforeNavigation) {
- const char* kEmbedderURL = "/browser_plugin_embedder.html";
- const std::string embedder_code =
- "document.getElementById('plugin').minwidth = 300;"
- "document.getElementById('plugin').minheight = 200;"
- "document.getElementById('plugin').maxwidth = 600;"
- "document.getElementById('plugin').maxheight = 400;"
- "document.getElementById('plugin').autosize = true;";
- StartBrowserPluginTest(
- kEmbedderURL, kHTMLForGuestWithSize, true, embedder_code);
- // Verify that the guest has been auto-sized.
- test_guest()->WaitForViewSize(gfx::Size(300, 400));
-}
-
-// This test verifies that enabling autosize resizes the guest and triggers
-// a 'sizechanged' event.
-IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, AutoSizeAfterNavigation) {
- const char* kEmbedderURL = "/browser_plugin_embedder.html";
- StartBrowserPluginTest(
- kEmbedderURL, kHTMLForGuestWithSize, true, std::string());
- RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
- test_embedder()->web_contents()->GetRenderViewHost());
-
- {
- const string16 expected_title = ASCIIToUTF16("AutoSize(300, 400)");
- content::TitleWatcher title_watcher(test_embedder()->web_contents(),
- expected_title);
- ExecuteSyncJSFunction(
- rvh,
- "document.getElementById('plugin').minwidth = 300;"
- "document.getElementById('plugin').minheight = 200;"
- "document.getElementById('plugin').maxwidth = 600;"
- "document.getElementById('plugin').maxheight = 400;"
- "document.getElementById('plugin').autosize = true;");
- string16 actual_title = title_watcher.WaitAndGetTitle();
- EXPECT_EQ(expected_title, actual_title);
- }
- {
- // Change the minwidth and verify that it causes relayout.
- const string16 expected_title = ASCIIToUTF16("AutoSize(350, 400)");
- content::TitleWatcher title_watcher(test_embedder()->web_contents(),
- expected_title);
- ExecuteSyncJSFunction(
- rvh, "document.getElementById('plugin').minwidth = 350;");
- string16 actual_title = title_watcher.WaitAndGetTitle();
- EXPECT_EQ(expected_title, actual_title);
- }
- {
- // Turn off autoSize and verify that the guest resizes to fit the container.
- ExecuteSyncJSFunction(
- rvh, "document.getElementById('plugin').autosize = null;");
- test_guest()->WaitForViewSize(gfx::Size(640, 480));
- }
-}
-
// Test for regression http://crbug.com/162961.
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, GetRenderViewHostAtPositionTest) {
const char kEmbedderURL[] = "/browser_plugin_embedder.html";
@@ -858,79 +789,6 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, GetRenderViewHostAtPositionTest) {
test_embedder()->last_rvh_at_position_response());
}
-// This test verifies that all autosize attributes can be removed
-// without crashing the plugin, or throwing errors.
-IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, RemoveAutosizeAttributes) {
- const char* kEmbedderURL = "/browser_plugin_embedder.html";
- const std::string embedder_code =
- "document.getElementById('plugin').minwidth = 300;"
- "document.getElementById('plugin').minheight = 200;"
- "document.getElementById('plugin').maxwidth = 600;"
- "document.getElementById('plugin').maxheight = 400;"
- "document.getElementById('plugin').name = 'name';"
- "document.getElementById('plugin').src = 'foo';"
- "document.getElementById('plugin').autosize = '';";
- StartBrowserPluginTest(
- kEmbedderURL, kHTMLForGuestWithSize, true, embedder_code);
- RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
- test_embedder()->web_contents()->GetRenderViewHost());
- RemoveAttributes(rvh, "maxheight, maxwidth, minheight, minwidth, autosize");
-
- // Verify that the guest resizes to fit the container (and hasn't crashed).
- test_guest()->WaitForViewSize(gfx::Size(640, 480));
- EXPECT_TRUE(IsAttributeNull(rvh, "maxheight"));
- EXPECT_TRUE(IsAttributeNull(rvh, "maxwidth"));
- EXPECT_TRUE(IsAttributeNull(rvh, "minheight"));
- EXPECT_TRUE(IsAttributeNull(rvh, "minwidth"));
- EXPECT_TRUE(IsAttributeNull(rvh, "autosize"));
-}
-
-// This test verifies that autosize works when some of the parameters are unset.
-IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, PartialAutosizeAttributes) {
- const char* kEmbedderURL = "/browser_plugin_embedder.html";
- const std::string embedder_code =
- "document.getElementById('plugin').minwidth = 300;"
- "document.getElementById('plugin').minheight = 200;"
- "document.getElementById('plugin').maxwidth = 700;"
- "document.getElementById('plugin').maxheight = 600;"
- "document.getElementById('plugin').autosize = '';";
- StartBrowserPluginTest(
- kEmbedderURL, kHTMLForGuestWithSize, true, embedder_code);
- RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
- test_embedder()->web_contents()->GetRenderViewHost());
- {
- // Remove an autosize attribute and verify that it causes relayout.
- const string16 expected_title = ASCIIToUTF16("AutoSize(640, 400)");
- content::TitleWatcher title_watcher(test_embedder()->web_contents(),
- expected_title);
- RemoveAttributes(rvh, "minwidth");
- string16 actual_title = title_watcher.WaitAndGetTitle();
- EXPECT_EQ(expected_title, actual_title);
- }
- {
- // Remove an autosize attribute and verify that it causes relayout.
- // Also tests that when minwidth > maxwidth, minwidth = maxwidth.
- const string16 expected_title = ASCIIToUTF16("AutoSize(700, 480)");
- content::TitleWatcher title_watcher(test_embedder()->web_contents(),
- expected_title);
- RemoveAttributes(rvh, "maxheight");
- ExecuteSyncJSFunction(
- rvh, "document.getElementById('plugin').minwidth = 800;"
- "document.getElementById('plugin').minheight = 800;");
- string16 actual_title = title_watcher.WaitAndGetTitle();
- EXPECT_EQ(expected_title, actual_title);
- }
- {
- // Remove maxwidth and make sure the size returns to plugin size.
- const string16 expected_title = ASCIIToUTF16("AutoSize(640, 480)");
- content::TitleWatcher title_watcher(test_embedder()->web_contents(),
- expected_title);
- RemoveAttributes(rvh, "maxwidth");
- string16 actual_title = title_watcher.WaitAndGetTitle();
- EXPECT_EQ(expected_title, actual_title);
- }
-}
-
// This test verifies that if IME is enabled in the embedder, it is also enabled
// in the guest.
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, VerifyInputMethodActive) {
@@ -941,4 +799,34 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, VerifyInputMethodActive) {
EXPECT_TRUE(rvh->input_method_active());
}
+// Verify that navigating to an invalid URL (e.g. 'http:') doesn't cause
+// a crash.
+IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, DoNotCrashOnInvalidNavigation) {
+ const char kEmbedderURL[] = "/browser_plugin_embedder.html";
+ StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, std::string());
+ TestBrowserPluginGuestDelegate* delegate =
+ new TestBrowserPluginGuestDelegate();
+ test_guest()->SetDelegate(delegate);
+
+ const char kValidSchemeWithEmptyURL[] = "http:";
+ ExecuteSyncJSFunction(
+ test_embedder()->web_contents()->GetRenderViewHost(),
+ base::StringPrintf("SetSrc('%s');", kValidSchemeWithEmptyURL));
+ EXPECT_TRUE(delegate->load_aborted());
+ EXPECT_FALSE(delegate->load_aborted_url().is_valid());
+ EXPECT_EQ(kValidSchemeWithEmptyURL,
+ delegate->load_aborted_url().possibly_invalid_spec());
+
+ delegate->ResetStates();
+
+ // Attempt a navigation to chrome-guest://abc123, which is a valid URL. But it
+ // 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));
+ EXPECT_TRUE(delegate->load_aborted());
+ EXPECT_TRUE(delegate->load_aborted_url().is_valid());
+}
+
} // namespace content
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
new file mode 100644
index 00000000000..28c27b7578e
--- /dev/null
+++ b/chromium/content/browser/browser_plugin/test_browser_plugin_guest_delegate.cc
@@ -0,0 +1,66 @@
+// Copyright 2013 The Chromium Authors. All rights 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/test_browser_plugin_guest_delegate.h"
+
+namespace content {
+
+TestBrowserPluginGuestDelegate::TestBrowserPluginGuestDelegate()
+ : load_aborted_(false) {
+}
+
+TestBrowserPluginGuestDelegate::~TestBrowserPluginGuestDelegate() {
+}
+
+void TestBrowserPluginGuestDelegate::ResetStates() {
+ load_aborted_ = false;
+ load_aborted_url_ = GURL();
+}
+
+void TestBrowserPluginGuestDelegate::AddMessageToConsole(
+ int32 level,
+ const string16& message,
+ int32 line_no,
+ const string16& source_id) {
+}
+
+void TestBrowserPluginGuestDelegate::Close() {
+}
+
+void TestBrowserPluginGuestDelegate::GuestProcessGone(
+ base::TerminationStatus status) {
+}
+
+bool TestBrowserPluginGuestDelegate::HandleKeyboardEvent(
+ const NativeWebKeyboardEvent& event) {
+ return BrowserPluginGuestDelegate::HandleKeyboardEvent(event);
+}
+
+void TestBrowserPluginGuestDelegate::LoadAbort(bool is_top_level,
+ const GURL& url,
+ const std::string& error_type) {
+ load_aborted_ = true;
+ load_aborted_url_ = url;
+}
+
+void TestBrowserPluginGuestDelegate::RendererResponsive() {
+}
+
+void TestBrowserPluginGuestDelegate::RendererUnresponsive() {
+}
+
+bool TestBrowserPluginGuestDelegate::RequestPermission(
+ BrowserPluginPermissionType permission_type,
+ const base::DictionaryValue& request_info,
+ const PermissionResponseCallback& callback) {
+ return BrowserPluginGuestDelegate::RequestPermission(permission_type,
+ request_info,
+ callback);
+}
+
+void TestBrowserPluginGuestDelegate::SizeChanged(const gfx::Size& old_size,
+ const gfx::Size& new_size) {
+}
+
+} // namespace content
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
new file mode 100644
index 00000000000..b6e7e9079f3
--- /dev/null
+++ b/chromium/content/browser/browser_plugin/test_browser_plugin_guest_delegate.h
@@ -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.
+
+#ifndef CONTENT_BROWSER_BROWSER_PLUGIN_TEST_BROWSER_PLUGIN_GUEST_DELEGATE_H_
+#define CONTENT_BROWSER_BROWSER_PLUGIN_TEST_BROWSER_PLUGIN_GUEST_DELEGATE_H_
+
+#include "content/public/browser/browser_plugin_guest_delegate.h"
+
+namespace content {
+
+class TestBrowserPluginGuestDelegate : public BrowserPluginGuestDelegate {
+ public:
+ TestBrowserPluginGuestDelegate();
+ virtual ~TestBrowserPluginGuestDelegate();
+
+ void ResetStates();
+
+ bool load_aborted() const { return load_aborted_; }
+ const GURL& load_aborted_url() const { return load_aborted_url_; }
+
+ private:
+ // Overridden from BrowserPluginGuestDelegate:
+ virtual void AddMessageToConsole(int32 level,
+ const string16& message,
+ int32 line_no,
+ const string16& source_id) OVERRIDE;
+ virtual void Close() OVERRIDE;
+ virtual void GuestProcessGone(base::TerminationStatus status) OVERRIDE;
+ virtual bool HandleKeyboardEvent(
+ const NativeWebKeyboardEvent& event) OVERRIDE;
+ virtual void LoadAbort(bool is_top_level,
+ const GURL& url,
+ const std::string& error_type) OVERRIDE;
+ virtual void RendererResponsive() OVERRIDE;
+ virtual void RendererUnresponsive() OVERRIDE;
+ virtual bool RequestPermission(
+ BrowserPluginPermissionType permission_type,
+ const base::DictionaryValue& request_info,
+ const PermissionResponseCallback& callback) OVERRIDE;
+ virtual void SizeChanged(const gfx::Size& old_size,
+ const gfx::Size& new_size) OVERRIDE;
+
+ bool load_aborted_;
+ GURL load_aborted_url_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestBrowserPluginGuestDelegate);
+};
+
+} // namespace content
+#endif // CONTENT_BROWSER_BROWSER_PLUGIN_TEST_BROWSER_PLUGIN_GUEST_DELEGATE_H_
diff --git a/chromium/content/browser/browser_shutdown_profile_dumper.cc b/chromium/content/browser/browser_shutdown_profile_dumper.cc
new file mode 100644
index 00000000000..70e3e5389c1
--- /dev/null
+++ b/chromium/content/browser/browser_shutdown_profile_dumper.cc
@@ -0,0 +1,139 @@
+// Copyright 2013 The Chromium Authors. All rights 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_shutdown_profile_dumper.h"
+
+#include "base/base_switches.h"
+#include "base/command_line.h"
+#include "base/debug/trace_event.h"
+#include "base/debug/trace_event_impl.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
+#include "base/threading/thread_restrictions.h"
+#include "content/public/common/content_switches.h"
+
+namespace content {
+
+BrowserShutdownProfileDumper::BrowserShutdownProfileDumper()
+ : blocks_(0),
+ dump_file_(NULL) {
+}
+
+BrowserShutdownProfileDumper::~BrowserShutdownProfileDumper() {
+ WriteTracesToDisc(GetFileName());
+}
+
+void BrowserShutdownProfileDumper::WriteTracesToDisc(
+ const base::FilePath& file_name) {
+ // Note: I have seen a usage of 0.000xx% when dumping - which fits easily.
+ // Since the tracer stops when the trace buffer is filled, we'd rather save
+ // what we have than nothing since we might see from the amount of events
+ // that caused the problem.
+ DVLOG(1) << "Flushing shutdown traces to disc. The buffer is %" <<
+ base::debug::TraceLog::GetInstance()->GetBufferPercentFull() <<
+ " full.";
+ DCHECK(!dump_file_);
+ dump_file_ = file_util::OpenFile(file_name, "w+");
+ if (!IsFileValid()) {
+ LOG(ERROR) << "Failed to open performance trace file: " <<
+ file_name.value();
+ return;
+ }
+ WriteString("{\"traceEvents\":");
+ WriteString("[");
+
+ // TraceLog::Flush() requires the calling thread to have a message loop.
+ // As the message loop of the current thread may have quit, start another
+ // thread for flushing the trace.
+ base::WaitableEvent flush_complete_event(false, false);
+ base::Thread flush_thread("browser_shutdown_trace_event_flush");
+ flush_thread.Start();
+ flush_thread.message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&BrowserShutdownProfileDumper::EndTraceAndFlush,
+ base::Unretained(this),
+ base::Unretained(&flush_complete_event)));
+
+ bool original_wait_allowed = base::ThreadRestrictions::SetWaitAllowed(true);
+ flush_complete_event.Wait();
+ base::ThreadRestrictions::SetWaitAllowed(original_wait_allowed);
+}
+
+void BrowserShutdownProfileDumper::EndTraceAndFlush(
+ base::WaitableEvent* flush_complete_event) {
+ while (base::debug::TraceLog::GetInstance()->IsEnabled())
+ base::debug::TraceLog::GetInstance()->SetDisabled();
+ base::debug::TraceLog::GetInstance()->Flush(
+ base::Bind(&BrowserShutdownProfileDumper::WriteTraceDataCollected,
+ base::Unretained(this),
+ base::Unretained(flush_complete_event)));
+}
+
+base::FilePath BrowserShutdownProfileDumper::GetFileName() {
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ base::FilePath trace_file =
+ command_line.GetSwitchValuePath(switches::kTraceShutdownFile);
+
+ if (!trace_file.empty())
+ return trace_file;
+
+ // Default to saving the startup trace into the current dir.
+ return base::FilePath().AppendASCII("chrometrace.log");
+}
+
+void BrowserShutdownProfileDumper::WriteTraceDataCollected(
+ base::WaitableEvent* flush_complete_event,
+ const scoped_refptr<base::RefCountedString>& events_str,
+ bool has_more_events) {
+ if (!IsFileValid()) {
+ flush_complete_event->Signal();
+ return;
+ }
+ if (blocks_) {
+ // Blocks are not comma separated. Beginning with the second block we
+ // start therefore to add one in front of the previous block.
+ WriteString(",");
+ }
+ ++blocks_;
+ WriteString(events_str->data());
+
+ if (!has_more_events) {
+ WriteString("]");
+ WriteString("}");
+ CloseFile();
+ flush_complete_event->Signal();
+ }
+}
+
+bool BrowserShutdownProfileDumper::IsFileValid() {
+ return dump_file_ && (ferror(dump_file_) == 0);
+}
+
+void BrowserShutdownProfileDumper::WriteString(const std::string& string) {
+ WriteChars(string.data(), string.size());
+}
+
+void BrowserShutdownProfileDumper::WriteChars(const char* chars, size_t size) {
+ if (!IsFileValid())
+ return;
+
+ size_t written = fwrite(chars, 1, size, dump_file_);
+ if (written != size) {
+ LOG(ERROR) << "Error " << ferror(dump_file_) <<
+ " in fwrite() to trace file";
+ CloseFile();
+ }
+}
+
+void BrowserShutdownProfileDumper::CloseFile() {
+ if (!dump_file_)
+ return;
+ file_util::CloseFile(dump_file_);
+ dump_file_ = NULL;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/browser_shutdown_profile_dumper.h b/chromium/content/browser/browser_shutdown_profile_dumper.h
new file mode 100644
index 00000000000..f98a32cb9ca
--- /dev/null
+++ b/chromium/content/browser/browser_shutdown_profile_dumper.h
@@ -0,0 +1,74 @@
+// Copyright 2013 The Chromium Authors. All 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_SHUTDOWN_PROFILE_DUMPER_H_
+#define CONTENT_BROWSER_BROWSER_SHUTDOWN_PROFILE_DUMPER_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/ref_counted_memory.h"
+#include "content/common/content_export.h"
+
+namespace base {
+class FilePath;
+class WaitableEvent;
+}
+
+namespace content {
+
+// This class is intended to dump the tracing results of the shutdown process
+// to a file before the browser process exits.
+// It will save the file either into the command line passed
+// "--trace-shutdown-file=<name>" parameter - or - to "chrometrace.log" in the
+// current directory.
+// Use the class with a scoped_ptr to get files written in the destructor.
+// Note that we cannot use the asynchronous file writer since the
+// |SequencedWorkerPool| will get killed in the shutdown process.
+class BrowserShutdownProfileDumper {
+ public:
+ BrowserShutdownProfileDumper();
+
+ ~BrowserShutdownProfileDumper();
+
+ private:
+ // Writes all traces which happened to disk.
+ void WriteTracesToDisc(const base::FilePath& file_name);
+
+ void EndTraceAndFlush(base::WaitableEvent* flush_complete_event);
+
+ // Returns the file name where we should save the trace dump to.
+ base::FilePath GetFileName();
+
+ // The callback for the |TraceLog::Flush| function. It saves all traces to
+ // disc.
+ void WriteTraceDataCollected(
+ base::WaitableEvent* flush_complete_event,
+ const scoped_refptr<base::RefCountedString>& events_str,
+ bool has_more_events);
+
+ // Returns true if the dump file is valid.
+ bool IsFileValid();
+
+ // Writes a string to the dump file.
+ void WriteString(const std::string& string);
+
+ // Write a buffer to the dump file.
+ void WriteChars(const char* chars, size_t size);
+
+ // Closes the dump file.
+ void CloseFile();
+
+ // The number of blocks we have already written.
+ int blocks_;
+ // For dumping the content to disc.
+ FILE* dump_file_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserShutdownProfileDumper);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_BROWSER_SHUTDOWN_PROFILE_DUMPER_H_
diff --git a/chromium/content/browser/browser_thread_impl.h b/chromium/content/browser/browser_thread_impl.h
index b16bb362351..167cc3b85a1 100644
--- a/chromium/content/browser/browser_thread_impl.h
+++ b/chromium/content/browser/browser_thread_impl.h
@@ -60,6 +60,7 @@ class CONTENT_EXPORT BrowserThreadImpl : public BrowserThread,
// For testing.
friend class ContentTestSuiteBaseListener;
+ friend class TestBrowserThreadBundle;
static void FlushThreadPoolHelper();
// The identifier of this thread. Only one thread can exist with a given
diff --git a/chromium/content/browser/browser_url_handler_impl.cc b/chromium/content/browser/browser_url_handler_impl.cc
index 56efe6b71b7..5ff1309f1a8 100644
--- a/chromium/content/browser/browser_url_handler_impl.cc
+++ b/chromium/content/browser/browser_url_handler_impl.cc
@@ -13,8 +13,7 @@
namespace content {
// Handles rewriting view-source URLs for what we'll actually load.
-static bool HandleViewSource(GURL* url,
- BrowserContext* browser_context) {
+static bool HandleViewSource(GURL* url, BrowserContext* browser_context) {
if (url->SchemeIs(kViewSourceScheme)) {
// Load the inner URL instead.
*url = GURL(url->path());
@@ -22,7 +21,7 @@ static bool HandleViewSource(GURL* url,
// 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[] = {
- chrome::kHttpScheme, chrome::kHttpsScheme, chrome::kFtpScheme,
+ kHttpScheme, kHttpsScheme, chrome::kFtpScheme,
chrome::kChromeDevToolsScheme, chrome::kChromeUIScheme,
chrome::kFileScheme, chrome::kFileSystemScheme
};
diff --git a/chromium/content/browser/byte_stream.cc b/chromium/content/browser/byte_stream.cc
index a8b8f29e9e6..7b0f9fb0f9a 100644
--- a/chromium/content/browser/byte_stream.cc
+++ b/chromium/content/browser/byte_stream.cc
@@ -61,6 +61,7 @@ class ByteStreamWriterImpl : public ByteStreamWriter {
virtual void Flush() OVERRIDE;
virtual void Close(int status) OVERRIDE;
virtual void RegisterCallback(const base::Closure& source_callback) OVERRIDE;
+ virtual size_t GetTotalBufferedBytes() const OVERRIDE;
// PostTask target from |ByteStreamReaderImpl::MaybeUpdateInput|.
static void UpdateWindow(scoped_refptr<LifetimeFlag> lifetime_flag,
@@ -209,6 +210,18 @@ bool ByteStreamWriterImpl::Write(
scoped_refptr<net::IOBuffer> buffer, size_t byte_count) {
DCHECK(my_task_runner_->RunsTasksOnCurrentThread());
+ // Check overflow.
+ //
+ // TODO(tyoshino): Discuss with content/browser/download developer and if
+ // they're fine with, set smaller limit and make it configurable.
+ size_t space_limit = std::numeric_limits<size_t>::max() -
+ GetTotalBufferedBytes();
+ if (byte_count > space_limit) {
+ // TODO(tyoshino): Tell the user that Write() failed.
+ // Ignore input.
+ return false;
+ }
+
input_contents_.push_back(std::make_pair(buffer, byte_count));
input_contents_size_ += byte_count;
@@ -216,7 +229,7 @@ bool ByteStreamWriterImpl::Write(
if (input_contents_size_ > total_buffer_size_ / kFractionBufferBeforeSending)
PostToPeer(false, 0);
- return (input_contents_size_ + output_size_used_ <= total_buffer_size_);
+ return GetTotalBufferedBytes() <= total_buffer_size_;
}
void ByteStreamWriterImpl::Flush() {
@@ -236,6 +249,13 @@ void ByteStreamWriterImpl::RegisterCallback(
space_available_callback_ = source_callback;
}
+size_t ByteStreamWriterImpl::GetTotalBufferedBytes() const {
+ DCHECK(my_task_runner_->RunsTasksOnCurrentThread());
+ // This sum doesn't overflow since Write() fails if this sum is going to
+ // overflow.
+ return input_contents_size_ + output_size_used_;
+}
+
// static
void ByteStreamWriterImpl::UpdateWindow(
scoped_refptr<LifetimeFlag> lifetime_flag, ByteStreamWriterImpl* target,
@@ -248,15 +268,16 @@ void ByteStreamWriterImpl::UpdateWindow(
void ByteStreamWriterImpl::UpdateWindowInternal(size_t bytes_consumed) {
DCHECK(my_task_runner_->RunsTasksOnCurrentThread());
+
+ bool was_above_limit = GetTotalBufferedBytes() > total_buffer_size_;
+
DCHECK_GE(output_size_used_, bytes_consumed);
output_size_used_ -= bytes_consumed;
// Callback if we were above the limit and we're now <= to it.
- size_t total_known_size_used =
- input_contents_size_ + output_size_used_;
+ bool no_longer_above_limit = GetTotalBufferedBytes() <= total_buffer_size_;
- if (total_known_size_used <= total_buffer_size_ &&
- (total_known_size_used + bytes_consumed > total_buffer_size_) &&
+ if (no_longer_above_limit && was_above_limit &&
!space_available_callback_.is_null())
space_available_callback_.Run();
}
diff --git a/chromium/content/browser/byte_stream.h b/chromium/content/browser/byte_stream.h
index 0b5640d0711..60b01634c5c 100644
--- a/chromium/content/browser/byte_stream.h
+++ b/chromium/content/browser/byte_stream.h
@@ -153,6 +153,10 @@ class CONTENT_EXPORT ByteStreamWriter {
// or after callbacks may be called).
// The callback will not be called after ByteStreamWriter destruction.
virtual void RegisterCallback(const base::Closure& source_callback) = 0;
+
+ // Returns the number of bytes sent to the reader but not yet reported by
+ // the reader as read.
+ virtual size_t GetTotalBufferedBytes() const = 0;
};
class CONTENT_EXPORT ByteStreamReader {
diff --git a/chromium/content/browser/byte_stream_unittest.cc b/chromium/content/browser/byte_stream_unittest.cc
index 04c5ae37533..f814e2f5d08 100644
--- a/chromium/content/browser/byte_stream_unittest.cc
+++ b/chromium/content/browser/byte_stream_unittest.cc
@@ -5,6 +5,7 @@
#include "content/browser/byte_stream.h"
#include <deque>
+#include <limits>
#include "base/bind.h"
#include "base/callback.h"
@@ -116,7 +117,10 @@ TEST_F(ByteStreamTest, ByteStream_PushBack) {
EXPECT_FALSE(Write(byte_stream_input.get(), 1024));
// Flush
byte_stream_input->Close(0);
+ EXPECT_EQ(4 * 1024U + 1U, byte_stream_input->GetTotalBufferedBytes());
message_loop_.RunUntilIdle();
+ // Data already sent to reader is also counted in.
+ EXPECT_EQ(4 * 1024U + 1U, byte_stream_input->GetTotalBufferedBytes());
// Pull the IO buffers out; do we get the same buffers and do they
// have the same contents?
@@ -144,6 +148,10 @@ TEST_F(ByteStreamTest, ByteStream_PushBack) {
EXPECT_EQ(ByteStreamReader::STREAM_COMPLETE,
byte_stream_output->Read(&output_io_buffer, &output_length));
+
+ message_loop_.RunUntilIdle();
+ // Reader now knows that all data is read out.
+ EXPECT_EQ(1024U, byte_stream_input->GetTotalBufferedBytes());
}
// Confirm that Flush() method makes the writer to send written contents to
@@ -579,4 +587,27 @@ TEST_F(ByteStreamTest, ByteStream_FlushWithoutAnyWrite) {
byte_stream_output->Read(&output_io_buffer, &output_length));
}
+TEST_F(ByteStreamTest, ByteStream_WriteOverflow) {
+ scoped_ptr<ByteStreamWriter> byte_stream_input;
+ scoped_ptr<ByteStreamReader> byte_stream_output;
+ CreateByteStream(
+ message_loop_.message_loop_proxy(), message_loop_.message_loop_proxy(),
+ std::numeric_limits<size_t>::max(),
+ &byte_stream_input, &byte_stream_output);
+
+ EXPECT_TRUE(Write(byte_stream_input.get(), 1));
+ // 1 + size_t max -> Overflow.
+ scoped_refptr<net::IOBuffer> empty_io_buffer;
+ EXPECT_FALSE(byte_stream_input->Write(empty_io_buffer,
+ std::numeric_limits<size_t>::max()));
+ message_loop_.RunUntilIdle();
+
+ // The first write is below PostToPeer threshold. We shouldn't get anything
+ // from the output.
+ scoped_refptr<net::IOBuffer> output_io_buffer;
+ size_t output_length;
+ EXPECT_EQ(ByteStreamReader::STREAM_EMPTY,
+ byte_stream_output->Read(&output_io_buffer, &output_length));
+}
+
} // namespace content
diff --git a/chromium/content/browser/child_process_launcher.cc b/chromium/content/browser/child_process_launcher.cc
index b5bb3f491f0..721cd5a88ed 100644
--- a/chromium/content/browser/child_process_launcher.cc
+++ b/chromium/content/browser/child_process_launcher.cc
@@ -35,6 +35,7 @@
#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"
+#include "content/common/child_process_sandbox_support_impl_linux.h"
#endif
#if defined(OS_POSIX)
@@ -74,7 +75,7 @@ class ChildProcessLauncher::Context
int ipcfd,
#elif defined(OS_POSIX)
bool use_zygote,
- const base::EnvironmentVector& environ,
+ const base::EnvironmentMap& environ,
int ipcfd,
#endif
CommandLine* cmd_line,
@@ -186,7 +187,7 @@ class ChildProcessLauncher::Context
int ipcfd,
#elif defined(OS_POSIX)
bool use_zygote,
- const base::EnvironmentVector& env,
+ const base::EnvironmentMap& env,
int ipcfd,
#endif
CommandLine* cmd_line) {
@@ -256,13 +257,13 @@ class ChildProcessLauncher::Context
RenderSandboxHostLinux::GetInstance()->GetRendererSocket();
fds_to_map.push_back(std::make_pair(
sandbox_fd,
- kSandboxIPCChannel + base::GlobalDescriptors::kBaseDescriptor));
+ GetSandboxFD()));
}
#endif // defined(OS_MACOSX)
// Actually launch the app.
base::LaunchOptions options;
- options.environ = &env;
+ options.environ = env;
options.fds_to_remap = &fds_to_map;
#if defined(OS_MACOSX)
@@ -414,7 +415,7 @@ ChildProcessLauncher::ChildProcessLauncher(
SandboxedProcessLauncherDelegate* delegate,
#elif defined(OS_POSIX)
bool use_zygote,
- const base::EnvironmentVector& environ,
+ const base::EnvironmentMap& environ,
int ipcfd,
#endif
CommandLine* cmd_line,
@@ -464,6 +465,11 @@ base::TerminationStatus ChildProcessLauncher::GetChildTerminationStatus(
context_->termination_status_ = ZygoteHostImpl::GetInstance()->
GetTerminationStatus(handle, known_dead, &context_->exit_code_);
} else
+#elif defined(OS_MACOSX)
+ if (known_dead) {
+ context_->termination_status_ =
+ base::GetKnownDeadTerminationStatus(handle, &context_->exit_code_);
+ } else
#endif
{
context_->termination_status_ =
diff --git a/chromium/content/browser/child_process_launcher.h b/chromium/content/browser/child_process_launcher.h
index 5a6e1f96e26..7ce780551f4 100644
--- a/chromium/content/browser/child_process_launcher.h
+++ b/chromium/content/browser/child_process_launcher.h
@@ -41,7 +41,7 @@ class CONTENT_EXPORT ChildProcessLauncher {
SandboxedProcessLauncherDelegate* delegate,
#elif defined(OS_POSIX)
bool use_zygote,
- const base::EnvironmentVector& environ,
+ const base::EnvironmentMap& environ,
int ipcfd,
#endif
CommandLine* cmd_line,
@@ -58,6 +58,11 @@ class CONTENT_EXPORT ChildProcessLauncher {
// Call this when the child process exits to know what happened to it.
// |known_dead| can be true if we already know the process is dead as it can
// help the implemention figure the proper TerminationStatus.
+ // On Linux, the use of |known_dead| is subtle and can be crucial if an
+ // accurate status is important. With |known_dead| set to false, a dead
+ // process could be seen as running. With |known_dead| set to true, the
+ // process will be killed if it was still running. See ZygoteHostImpl for
+ // more discussion of Linux implementation details.
// |exit_code| is the exit code of the process if it exited (e.g. status from
// waitpid if on posix, from GetExitCodeProcess on Windows). |exit_code| may
// be NULL.
diff --git a/chromium/content/browser/child_process_security_policy_browsertest.cc b/chromium/content/browser/child_process_security_policy_browsertest.cc
index db27a533ea9..c7cfe39c167 100644
--- a/chromium/content/browser/child_process_security_policy_browsertest.cc
+++ b/chromium/content/browser/child_process_security_policy_browsertest.cc
@@ -10,7 +10,7 @@
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/result_codes.h"
-#include "content/shell/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/content/browser/child_process_security_policy_impl.cc b/chromium/content/browser/child_process_security_policy_impl.cc
index aefbf71fa62..6933f9e0b1d 100644
--- a/chromium/content/browser/child_process_security_policy_impl.cc
+++ b/chromium/content/browser/child_process_security_policy_impl.cc
@@ -11,7 +11,9 @@
#include "base/platform_file.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
+#include "content/browser/plugin_process_host.h"
#include "content/browser/site_instance_impl.h"
+#include "content/public/browser/child_process_data.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/bindings_policy.h"
@@ -51,7 +53,7 @@ const int kEnumerateDirectoryPermissions =
base::PLATFORM_FILE_ENUMERATE;
// TODO(tommycli): These flag sets need some work to make more obvious.
-// Why for instance, does Create|Write != Create|Write? http://crbug.com/263150
+// Why for instance, does Create|Write != CreateWrite? http://crbug.com/263150
const int kCreateReadWriteFilePermissions =
kReadFilePermissions |
kWriteFilePermissions |
@@ -75,7 +77,8 @@ class ChildProcessSecurityPolicyImpl::SecurityState {
public:
SecurityState()
: enabled_bindings_(0),
- can_read_raw_cookies_(false) { }
+ can_read_raw_cookies_(false),
+ can_send_midi_sysex_(false) { }
~SecurityState() {
scheme_policy_.clear();
@@ -150,6 +153,10 @@ class ChildProcessSecurityPolicyImpl::SecurityState {
can_read_raw_cookies_ = false;
}
+ void GrantPermissionForMIDISysEx() {
+ can_send_midi_sysex_ = true;
+ }
+
// Determine whether permission has been granted to request |url|.
bool CanRequestURL(const GURL& url) {
// Having permission to a scheme implies permssion to all of its URLs.
@@ -245,6 +252,10 @@ class ChildProcessSecurityPolicyImpl::SecurityState {
return can_read_raw_cookies_;
}
+ bool can_send_midi_sysex() const {
+ return can_send_midi_sysex_;
+ }
+
private:
typedef std::map<std::string, bool> SchemeMap;
@@ -270,6 +281,8 @@ class ChildProcessSecurityPolicyImpl::SecurityState {
bool can_read_raw_cookies_;
+ bool can_send_midi_sysex_;
+
GURL origin_lock_;
// The set of isolated filesystems the child process is permitted to access.
@@ -280,8 +293,8 @@ class ChildProcessSecurityPolicyImpl::SecurityState {
ChildProcessSecurityPolicyImpl::ChildProcessSecurityPolicyImpl() {
// We know about these schemes and believe them to be safe.
- RegisterWebSafeScheme(chrome::kHttpScheme);
- RegisterWebSafeScheme(chrome::kHttpsScheme);
+ RegisterWebSafeScheme(kHttpScheme);
+ RegisterWebSafeScheme(kHttpsScheme);
RegisterWebSafeScheme(chrome::kFtpScheme);
RegisterWebSafeScheme(chrome::kDataScheme);
RegisterWebSafeScheme("feed");
@@ -290,7 +303,7 @@ ChildProcessSecurityPolicyImpl::ChildProcessSecurityPolicyImpl() {
// We know about the following pseudo schemes and treat them specially.
RegisterPseudoScheme(chrome::kAboutScheme);
- RegisterPseudoScheme(chrome::kJavaScriptScheme);
+ RegisterPseudoScheme(kJavaScriptScheme);
RegisterPseudoScheme(kViewSourceScheme);
}
@@ -487,6 +500,16 @@ void ChildProcessSecurityPolicyImpl::GrantCopyIntoFileSystem(
kCreateFilePermissions);
}
+void ChildProcessSecurityPolicyImpl::GrantSendMIDISysExMessage(int child_id) {
+ base::AutoLock lock(lock_);
+
+ SecurityStateMap::iterator state = security_state_.find(child_id);
+ if (state == security_state_.end())
+ return;
+
+ state->second->GrantPermissionForMIDISysEx();
+}
+
void ChildProcessSecurityPolicyImpl::GrantScheme(int child_id,
const std::string& scheme) {
base::AutoLock lock(lock_);
@@ -781,6 +804,17 @@ 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().process_type == PROCESS_TYPE_PLUGIN) {
+ // NPAPI plugin processes are unsandboxed and so are trusted. Plugins
+ // can make request to any origin.
+ return true;
+ }
+ break;
+ }
+ }
+
base::AutoLock lock(lock_);
SecurityStateMap::iterator state = security_state_.find(child_id);
if (state == security_state_.end())
@@ -829,4 +863,14 @@ void ChildProcessSecurityPolicyImpl::RegisterFileSystemPermissionPolicy(
file_system_policy_map_[type] = policy;
}
+bool ChildProcessSecurityPolicyImpl::CanSendMIDISysExMessage(int child_id) {
+ base::AutoLock lock(lock_);
+
+ SecurityStateMap::iterator state = security_state_.find(child_id);
+ if (state == security_state_.end())
+ return false;
+
+ return state->second->can_send_midi_sysex();
+}
+
} // namespace content
diff --git a/chromium/content/browser/child_process_security_policy_impl.h b/chromium/content/browser/child_process_security_policy_impl.h
index 3477f1edb1a..0a874b3beb4 100644
--- a/chromium/content/browser/child_process_security_policy_impl.h
+++ b/chromium/content/browser/child_process_security_policy_impl.h
@@ -122,6 +122,9 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
// Revoke read raw cookies permission.
void RevokeReadRawCookies(int child_id);
+ // Grants permission to send system exclusive message to any MIDI devices.
+ void GrantSendMIDISysExMessage(int child_id);
+
// Before servicing a child process's request for a URL, the browser should
// call this method to determine whether the process has the capability to
// request the URL.
@@ -138,20 +141,6 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
// the browser should call this method to check for the capability.
bool CanReadDirectory(int child_id, const base::FilePath& directory);
- // 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.
- 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.
- bool HasPermissionsForFileSystemFile(int child_id,
- const fileapi::FileSystemURL& url,
- int permissions);
-
// 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);
@@ -200,11 +189,15 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
fileapi::FileSystemType type,
int policy);
+ // Returns true if sending system exclusive messages is allowed.
+ bool CanSendMIDISysExMessage(int child_id);
+
private:
friend class ChildProcessSecurityPolicyInProcessBrowserTest;
friend class ChildProcessSecurityPolicyTest;
FRIEND_TEST_ALL_PREFIXES(ChildProcessSecurityPolicyInProcessBrowserTest,
NoLeak);
+ FRIEND_TEST_ALL_PREFIXES(ChildProcessSecurityPolicyTest, FilePermissions);
class SecurityState;
@@ -241,6 +234,20 @@ 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.
+ 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.
+ bool HasPermissionsForFileSystemFile(int child_id,
+ const fileapi::FileSystemURL& url,
+ int permissions);
+
// 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 b914eac549a..247a74f69d5 100644
--- a/chromium/content/browser/child_process_security_policy_unittest.cc
+++ b/chromium/content/browser/child_process_security_policy_unittest.cc
@@ -99,8 +99,8 @@ TEST_F(ChildProcessSecurityPolicyTest, IsWebSafeSchemeTest) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
- EXPECT_TRUE(p->IsWebSafeScheme(chrome::kHttpScheme));
- EXPECT_TRUE(p->IsWebSafeScheme(chrome::kHttpsScheme));
+ EXPECT_TRUE(p->IsWebSafeScheme(kHttpScheme));
+ EXPECT_TRUE(p->IsWebSafeScheme(kHttpsScheme));
EXPECT_TRUE(p->IsWebSafeScheme(chrome::kFtpScheme));
EXPECT_TRUE(p->IsWebSafeScheme(chrome::kDataScheme));
EXPECT_TRUE(p->IsWebSafeScheme("feed"));
@@ -119,7 +119,7 @@ TEST_F(ChildProcessSecurityPolicyTest, IsPseudoSchemeTest) {
ChildProcessSecurityPolicyImpl::GetInstance();
EXPECT_TRUE(p->IsPseudoScheme(chrome::kAboutScheme));
- EXPECT_TRUE(p->IsPseudoScheme(chrome::kJavaScriptScheme));
+ EXPECT_TRUE(p->IsPseudoScheme(kJavaScriptScheme));
EXPECT_TRUE(p->IsPseudoScheme(kViewSourceScheme));
EXPECT_FALSE(p->IsPseudoScheme("registered-pseudo-scheme"));
diff --git a/chromium/content/browser/database_browsertest.cc b/chromium/content/browser/database_browsertest.cc
index 305d8ff94c0..373a06f2a70 100644
--- a/chromium/content/browser/database_browsertest.cc
+++ b/chromium/content/browser/database_browsertest.cc
@@ -11,7 +11,7 @@
#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/shell.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/net/url_request_mock_http_job.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 6748d744b71..8d4919c4d58 100644
--- a/chromium/content/browser/device_orientation/data_fetcher_impl_android.cc
+++ b/chromium/content/browser/device_orientation/data_fetcher_impl_android.cc
@@ -26,7 +26,9 @@ const int kPeriodInMilliseconds = 100;
DataFetcherImplAndroid::DataFetcherImplAndroid()
: number_active_device_motion_sensors_(0),
device_motion_buffer_(NULL),
- is_buffer_ready_(false) {
+ device_orientation_buffer_(NULL),
+ is_motion_buffer_ready_(false),
+ is_orientation_buffer_ready_(false) {
memset(received_motion_data_, 0, sizeof(received_motion_data_));
device_orientation_.Reset(
Java_DeviceMotionAndOrientation_getInstance(AttachCurrentThread()));
@@ -66,18 +68,41 @@ const Orientation* DataFetcherImplAndroid::GetOrientation() {
void DataFetcherImplAndroid::GotOrientation(
JNIEnv*, jobject, double alpha, double beta, double gamma) {
- base::AutoLock autolock(next_orientation_lock_);
+ {
+ // 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;
+ }
- Orientation* orientation = new Orientation();
- orientation->set_alpha(alpha);
- orientation->set_beta(beta);
- orientation->set_gamma(gamma);
- orientation->set_absolute(true);
- next_orientation_ = orientation;
+ 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);
+ }
}
void DataFetcherImplAndroid::GotAcceleration(
JNIEnv*, jobject, double x, double y, double z) {
+ base::AutoLock autolock(motion_buffer_lock_);
+
+ if (!device_motion_buffer_)
+ return;
+
device_motion_buffer_->seqlock.WriteBegin();
device_motion_buffer_->data.accelerationX = x;
device_motion_buffer_->data.hasAccelerationX = true;
@@ -87,14 +112,19 @@ void DataFetcherImplAndroid::GotAcceleration(
device_motion_buffer_->data.hasAccelerationZ = true;
device_motion_buffer_->seqlock.WriteEnd();
- if (!is_buffer_ready_) {
+ if (!is_motion_buffer_ready_) {
received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION] = 1;
- CheckBufferReadyToRead();
+ CheckMotionBufferReadyToRead();
}
}
void DataFetcherImplAndroid::GotAccelerationIncludingGravity(
JNIEnv*, jobject, double x, double y, double z) {
+ base::AutoLock autolock(motion_buffer_lock_);
+
+ if (!device_motion_buffer_)
+ return;
+
device_motion_buffer_->seqlock.WriteBegin();
device_motion_buffer_->data.accelerationIncludingGravityX = x;
device_motion_buffer_->data.hasAccelerationIncludingGravityX = true;
@@ -104,14 +134,19 @@ void DataFetcherImplAndroid::GotAccelerationIncludingGravity(
device_motion_buffer_->data.hasAccelerationIncludingGravityZ = true;
device_motion_buffer_->seqlock.WriteEnd();
- if (!is_buffer_ready_) {
+ if (!is_motion_buffer_ready_) {
received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY] = 1;
- CheckBufferReadyToRead();
+ CheckMotionBufferReadyToRead();
}
}
void DataFetcherImplAndroid::GotRotationRate(
JNIEnv*, jobject, double alpha, double beta, double gamma) {
+ base::AutoLock autolock(motion_buffer_lock_);
+
+ if (!device_motion_buffer_)
+ return;
+
device_motion_buffer_->seqlock.WriteBegin();
device_motion_buffer_->data.rotationRateAlpha = alpha;
device_motion_buffer_->data.hasRotationRateAlpha = true;
@@ -121,9 +156,9 @@ void DataFetcherImplAndroid::GotRotationRate(
device_motion_buffer_->data.hasRotationRateGamma = true;
device_motion_buffer_->seqlock.WriteEnd();
- if (!is_buffer_ready_) {
+ if (!is_motion_buffer_ready_) {
received_motion_data_[RECEIVED_MOTION_DATA_ROTATION_RATE] = 1;
- CheckBufferReadyToRead();
+ CheckMotionBufferReadyToRead();
}
}
@@ -151,26 +186,41 @@ int DataFetcherImplAndroid::GetNumberActiveDeviceMotionSensors() {
// ----- Shared memory API methods
+// --- Device Motion
+
bool DataFetcherImplAndroid::StartFetchingDeviceMotionData(
DeviceMotionHardwareBuffer* buffer) {
- device_motion_buffer_ = buffer;
- ClearInternalBuffers();
+ DCHECK(buffer);
+ {
+ base::AutoLock autolock(motion_buffer_lock_);
+ device_motion_buffer_ = buffer;
+ ClearInternalMotionBuffers();
+ }
bool success = Start(DeviceData::kTypeMotion);
// If no motion data can ever be provided, the number of active device motion
// sensors will be zero. In that case flag the shared memory buffer
// as ready to read, as it will not change anyway.
number_active_device_motion_sensors_ = GetNumberActiveDeviceMotionSensors();
- CheckBufferReadyToRead();
+ {
+ base::AutoLock autolock(motion_buffer_lock_);
+ CheckMotionBufferReadyToRead();
+ }
return success;
}
void DataFetcherImplAndroid::StopFetchingDeviceMotionData() {
Stop(DeviceData::kTypeMotion);
- ClearInternalBuffers();
+ {
+ base::AutoLock autolock(motion_buffer_lock_);
+ if (device_motion_buffer_) {
+ ClearInternalMotionBuffers();
+ device_motion_buffer_ = NULL;
+ }
+ }
}
-void DataFetcherImplAndroid::CheckBufferReadyToRead() {
+void DataFetcherImplAndroid::CheckMotionBufferReadyToRead() {
if (received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION] +
received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY] +
received_motion_data_[RECEIVED_MOTION_DATA_ROTATION_RATE] ==
@@ -178,21 +228,50 @@ void DataFetcherImplAndroid::CheckBufferReadyToRead() {
device_motion_buffer_->seqlock.WriteBegin();
device_motion_buffer_->data.interval = kPeriodInMilliseconds;
device_motion_buffer_->seqlock.WriteEnd();
- SetBufferReadyStatus(true);
+ SetMotionBufferReadyStatus(true);
}
}
-void DataFetcherImplAndroid::SetBufferReadyStatus(bool ready) {
+void DataFetcherImplAndroid::SetMotionBufferReadyStatus(bool ready) {
device_motion_buffer_->seqlock.WriteBegin();
device_motion_buffer_->data.allAvailableSensorsAreActive = ready;
device_motion_buffer_->seqlock.WriteEnd();
- is_buffer_ready_ = ready;
+ is_motion_buffer_ready_ = ready;
}
-void DataFetcherImplAndroid::ClearInternalBuffers() {
+void DataFetcherImplAndroid::ClearInternalMotionBuffers() {
memset(received_motion_data_, 0, sizeof(received_motion_data_));
number_active_device_motion_sensors_ = 0;
- SetBufferReadyStatus(false);
+ SetMotionBufferReadyStatus(false);
+}
+
+// --- Device Orientation
+
+void DataFetcherImplAndroid::SetOrientationBufferReadyStatus(bool ready) {
+ device_orientation_buffer_->seqlock.WriteBegin();
+ device_orientation_buffer_->data.allAvailableSensorsAreActive = ready;
+ device_orientation_buffer_->seqlock.WriteEnd();
+ is_orientation_buffer_ready_ = ready;
+}
+
+bool DataFetcherImplAndroid::StartFetchingDeviceOrientationData(
+ DeviceOrientationHardwareBuffer* buffer) {
+ DCHECK(buffer);
+ 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);
+ return success;
+}
+
+void DataFetcherImplAndroid::StopFetchingDeviceOrientationData() {
+ Stop(DeviceData::kTypeOrientation);
+ if (device_orientation_buffer_) {
+ SetOrientationBufferReadyStatus(false);
+ device_orientation_buffer_ = NULL;
+ }
}
} // namespace content
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 9926e7d1464..f348e1d3e54 100644
--- a/chromium/content/browser/device_orientation/data_fetcher_impl_android.h
+++ b/chromium/content/browser/device_orientation/data_fetcher_impl_android.h
@@ -11,6 +11,7 @@
#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_orientation_hardware_buffer.h"
template<typename T> struct DefaultSingletonTraits;
@@ -55,6 +56,10 @@ class CONTENT_EXPORT DataFetcherImplAndroid {
bool StartFetchingDeviceMotionData(DeviceMotionHardwareBuffer* buffer);
void StopFetchingDeviceMotionData();
+ bool StartFetchingDeviceOrientationData(
+ DeviceOrientationHardwareBuffer* buffer);
+ void StopFetchingDeviceOrientationData();
+
protected:
DataFetcherImplAndroid();
virtual ~DataFetcherImplAndroid();
@@ -66,9 +71,11 @@ class CONTENT_EXPORT DataFetcherImplAndroid {
const Orientation* GetOrientation();
- void CheckBufferReadyToRead();
- void SetBufferReadyStatus(bool ready);
- void ClearInternalBuffers();
+ void CheckMotionBufferReadyToRead();
+ void SetMotionBufferReadyStatus(bool ready);
+ void ClearInternalMotionBuffers();
+
+ void SetOrientationBufferReadyStatus(bool ready);
enum {
RECEIVED_MOTION_DATA_ACCELERATION = 0,
@@ -88,7 +95,11 @@ class CONTENT_EXPORT DataFetcherImplAndroid {
int number_active_device_motion_sensors_;
int received_motion_data_[RECEIVED_MOTION_DATA_MAX];
DeviceMotionHardwareBuffer* device_motion_buffer_;
- bool is_buffer_ready_;
+ DeviceOrientationHardwareBuffer* device_orientation_buffer_;
+ bool is_motion_buffer_ready_;
+ bool is_orientation_buffer_ready_;
+
+ base::Lock motion_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 85d5184689e..d12c8c6feb1 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
@@ -42,10 +42,12 @@ class FakeDataFetcherImplAndroid : public DataFetcherImplAndroid {
class AndroidDataFetcherTest : public testing::Test {
protected:
AndroidDataFetcherTest() {
- buffer_.reset(new DeviceMotionHardwareBuffer);
+ motion_buffer_.reset(new DeviceMotionHardwareBuffer);
+ orientation_buffer_.reset(new DeviceOrientationHardwareBuffer);
}
- scoped_ptr<DeviceMotionHardwareBuffer> buffer_;
+ scoped_ptr<DeviceMotionHardwareBuffer> motion_buffer_;
+ scoped_ptr<DeviceOrientationHardwareBuffer> orientation_buffer_;
};
TEST_F(AndroidDataFetcherTest, ThreeDeviceMotionSensorsActive) {
@@ -53,21 +55,39 @@ TEST_F(AndroidDataFetcherTest, ThreeDeviceMotionSensorsActive) {
FakeDataFetcherImplAndroid fetcher;
fetcher.SetNumberActiveDeviceMotionSensors(3);
- fetcher.StartFetchingDeviceMotionData(buffer_.get());
- ASSERT_FALSE(buffer_->data.allAvailableSensorsAreActive);
+ fetcher.StartFetchingDeviceMotionData(motion_buffer_.get());
+ ASSERT_FALSE(motion_buffer_->data.allAvailableSensorsAreActive);
fetcher.GotAcceleration(0, 0, 1, 2, 3);
- ASSERT_FALSE(buffer_->data.allAvailableSensorsAreActive);
-
- fetcher.GotAccelerationIncludingGravity(0, 0, 1, 2, 3);
- ASSERT_FALSE(buffer_->data.allAvailableSensorsAreActive);
-
- fetcher.GotRotationRate(0, 0, 1, 2, 3);
- ASSERT_TRUE(buffer_->data.allAvailableSensorsAreActive);
- ASSERT_EQ(kPeriodInMilliseconds, buffer_->data.interval);
+ ASSERT_FALSE(motion_buffer_->data.allAvailableSensorsAreActive);
+ ASSERT_EQ(1, motion_buffer_->data.accelerationX);
+ ASSERT_TRUE(motion_buffer_->data.hasAccelerationX);
+ ASSERT_EQ(2, motion_buffer_->data.accelerationY);
+ ASSERT_TRUE(motion_buffer_->data.hasAccelerationY);
+ ASSERT_EQ(3, motion_buffer_->data.accelerationZ);
+ ASSERT_TRUE(motion_buffer_->data.hasAccelerationZ);
+
+ fetcher.GotAccelerationIncludingGravity(0, 0, 4, 5, 6);
+ ASSERT_FALSE(motion_buffer_->data.allAvailableSensorsAreActive);
+ ASSERT_EQ(4, motion_buffer_->data.accelerationIncludingGravityX);
+ ASSERT_TRUE(motion_buffer_->data.hasAccelerationIncludingGravityX);
+ ASSERT_EQ(5, motion_buffer_->data.accelerationIncludingGravityY);
+ ASSERT_TRUE(motion_buffer_->data.hasAccelerationIncludingGravityY);
+ ASSERT_EQ(6, motion_buffer_->data.accelerationIncludingGravityZ);
+ ASSERT_TRUE(motion_buffer_->data.hasAccelerationIncludingGravityZ);
+
+ fetcher.GotRotationRate(0, 0, 7, 8, 9);
+ ASSERT_TRUE(motion_buffer_->data.allAvailableSensorsAreActive);
+ ASSERT_EQ(7, motion_buffer_->data.rotationRateAlpha);
+ ASSERT_TRUE(motion_buffer_->data.hasRotationRateAlpha);
+ ASSERT_EQ(8, motion_buffer_->data.rotationRateBeta);
+ 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);
fetcher.StopFetchingDeviceMotionData();
- ASSERT_FALSE(buffer_->data.allAvailableSensorsAreActive);
+ ASSERT_FALSE(motion_buffer_->data.allAvailableSensorsAreActive);
}
TEST_F(AndroidDataFetcherTest, TwoDeviceMotionSensorsActive) {
@@ -75,18 +95,18 @@ TEST_F(AndroidDataFetcherTest, TwoDeviceMotionSensorsActive) {
FakeDataFetcherImplAndroid fetcher;
fetcher.SetNumberActiveDeviceMotionSensors(2);
- fetcher.StartFetchingDeviceMotionData(buffer_.get());
- ASSERT_FALSE(buffer_->data.allAvailableSensorsAreActive);
+ fetcher.StartFetchingDeviceMotionData(motion_buffer_.get());
+ ASSERT_FALSE(motion_buffer_->data.allAvailableSensorsAreActive);
fetcher.GotAcceleration(0, 0, 1, 2, 3);
- ASSERT_FALSE(buffer_->data.allAvailableSensorsAreActive);
+ ASSERT_FALSE(motion_buffer_->data.allAvailableSensorsAreActive);
fetcher.GotAccelerationIncludingGravity(0, 0, 1, 2, 3);
- ASSERT_TRUE(buffer_->data.allAvailableSensorsAreActive);
- ASSERT_EQ(kPeriodInMilliseconds, buffer_->data.interval);
+ ASSERT_TRUE(motion_buffer_->data.allAvailableSensorsAreActive);
+ ASSERT_EQ(kPeriodInMilliseconds, motion_buffer_->data.interval);
fetcher.StopFetchingDeviceMotionData();
- ASSERT_FALSE(buffer_->data.allAvailableSensorsAreActive);
+ ASSERT_FALSE(motion_buffer_->data.allAvailableSensorsAreActive);
}
TEST_F(AndroidDataFetcherTest, ZeroDeviceMotionSensorsActive) {
@@ -94,14 +114,35 @@ TEST_F(AndroidDataFetcherTest, ZeroDeviceMotionSensorsActive) {
FakeDataFetcherImplAndroid fetcher;
fetcher.SetNumberActiveDeviceMotionSensors(0);
- fetcher.StartFetchingDeviceMotionData(buffer_.get());
- ASSERT_TRUE(buffer_->data.allAvailableSensorsAreActive);
- ASSERT_EQ(kPeriodInMilliseconds, buffer_->data.interval);
+ fetcher.StartFetchingDeviceMotionData(motion_buffer_.get());
+ ASSERT_TRUE(motion_buffer_->data.allAvailableSensorsAreActive);
+ ASSERT_EQ(kPeriodInMilliseconds, motion_buffer_->data.interval);
fetcher.StopFetchingDeviceMotionData();
- ASSERT_FALSE(buffer_->data.allAvailableSensorsAreActive);
+ ASSERT_FALSE(motion_buffer_->data.allAvailableSensorsAreActive);
}
+TEST_F(AndroidDataFetcherTest, DeviceOrientationSensorsActive) {
+ FakeDataFetcherImplAndroid::Register(base::android::AttachCurrentThread());
+ FakeDataFetcherImplAndroid fetcher;
+
+ fetcher.StartFetchingDeviceOrientationData(orientation_buffer_.get());
+ ASSERT_FALSE(orientation_buffer_->data.allAvailableSensorsAreActive);
+
+ fetcher.GotOrientation(0, 0, 1, 2, 3);
+ ASSERT_TRUE(orientation_buffer_->data.allAvailableSensorsAreActive);
+ ASSERT_EQ(1, orientation_buffer_->data.alpha);
+ ASSERT_TRUE(orientation_buffer_->data.hasAlpha);
+ ASSERT_EQ(2, orientation_buffer_->data.beta);
+ ASSERT_TRUE(orientation_buffer_->data.hasBeta);
+ ASSERT_EQ(3, orientation_buffer_->data.gamma);
+ ASSERT_TRUE(orientation_buffer_->data.hasGamma);
+
+ fetcher.StopFetchingDeviceOrientationData();
+ ASSERT_FALSE(orientation_buffer_->data.allAvailableSensorsAreActive);
+}
+
+
} // namespace
} // namespace content
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 dc5e92ae160..dad1cb60dd2 100644
--- a/chromium/content/browser/device_orientation/data_fetcher_shared_memory.h
+++ b/chromium/content/browser/device_orientation/data_fetcher_shared_memory.h
@@ -5,48 +5,59 @@
#ifndef CONTENT_BROWSER_DEVICE_ORIENTATION_DATA_FETCHER_SHARED_MEMORY_H_
#define CONTENT_BROWSER_DEVICE_ORIENTATION_DATA_FETCHER_SHARED_MEMORY_H_
-#include "content/browser/device_orientation/device_data.h"
+#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_orientation_hardware_buffer.h"
+#endif
-namespace WebKit {
-class WebDeviceMotionData;
-}
+#if defined(OS_MACOSX)
+class SuddenMotionSensor;
+#elif defined(OS_WIN)
+#include <SensorsApi.h>
+#include "base/win/scoped_comptr.h"
+#endif
namespace content {
-class CONTENT_EXPORT DataFetcherSharedMemory {
+class CONTENT_EXPORT DataFetcherSharedMemory
+ : public DataFetcherSharedMemoryBase {
+
public:
- DataFetcherSharedMemory()
- : device_motion_buffer_(NULL),
- started_(false) { }
+ DataFetcherSharedMemory();
virtual ~DataFetcherSharedMemory();
- // Returns true if this fetcher needs explicit calls to fetch the data.
- // Called from any thread.
- virtual bool NeedsPolling();
-
- // If this fetcher NeedsPolling() is true, this method will update the
- // buffer with the latest device motion data.
- // Returns true if there was any motion data to update the buffer with.
- // Called from the DeviceMotionProvider::PollingThread.
- virtual bool FetchDeviceMotionDataIntoBuffer();
-
- // Returns true if the relevant sensors could be successfully activated.
- // This method should be called before any calls to
- // FetchDeviceMotionDataIntoBuffer().
- // If NeedsPolling() is true this method should be called from the
- // PollingThread.
- virtual bool StartFetchingDeviceMotionData(
- DeviceMotionHardwareBuffer* buffer);
-
- // Indicates to the fetcher to stop fetching device data.
- // If NeedsPolling() is true this method should be called from the
- // PollingThread.
- virtual void StopFetchingDeviceMotionData();
-
private:
- DeviceMotionHardwareBuffer* device_motion_buffer_;
- bool started_;
+ virtual bool Start(ConsumerType consumer_type, void* buffer) OVERRIDE;
+ virtual bool Stop(ConsumerType consumer_type) OVERRIDE;
+
+#if !defined(OS_ANDROID)
+ DeviceMotionHardwareBuffer* motion_buffer_;
+ DeviceOrientationHardwareBuffer* orientation_buffer_;
+#endif
+#if defined(OS_MACOSX)
+ virtual void Fetch(unsigned consumer_bitmask) OVERRIDE;
+ virtual bool IsPolling() const OVERRIDE;
+
+ scoped_ptr<SuddenMotionSensor> sudden_motion_sensor_;
+#elif defined(OS_WIN)
+ class SensorEventSink;
+ class SensorEventSinkMotion;
+ class SensorEventSinkOrientation;
+
+ virtual bool IsPolling() const OVERRIDE;
+ virtual base::TimeDelta GetPollDelay() const OVERRIDE;
+
+ bool RegisterForSensor(REFSENSOR_TYPE_ID sensor_type, ISensor** sensor,
+ scoped_refptr<SensorEventSink> event_sink);
+ void DisableSensors(ConsumerType consumer_type);
+ void SetBufferAvailableState(ConsumerType consumer_type, bool enabled);
+
+ base::win::ScopedComPtr<ISensor> sensor_inclinometer_;
+ base::win::ScopedComPtr<ISensor> sensor_accelerometer_;
+ base::win::ScopedComPtr<ISensor> sensor_gyrometer_;
+#endif
DISALLOW_COPY_AND_ASSIGN(DataFetcherSharedMemory);
};
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 8f6e202c042..3f00c3d179f 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
@@ -2,39 +2,52 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "data_fetcher_shared_memory.h"
+#include "content/browser/device_orientation/data_fetcher_shared_memory.h"
#include "base/logging.h"
-#include "data_fetcher_impl_android.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_orientation_hardware_buffer.h"
namespace content {
-DataFetcherSharedMemory::~DataFetcherSharedMemory() {
- if (started_)
- StopFetchingDeviceMotionData();
+DataFetcherSharedMemory::DataFetcherSharedMemory() {
}
-bool DataFetcherSharedMemory::NeedsPolling() {
- return false;
-}
-
-bool DataFetcherSharedMemory::FetchDeviceMotionDataIntoBuffer() {
- NOTREACHED();
- return false;
+DataFetcherSharedMemory::~DataFetcherSharedMemory() {
}
-bool DataFetcherSharedMemory::StartFetchingDeviceMotionData(
- DeviceMotionHardwareBuffer* buffer) {
+bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) {
DCHECK(buffer);
- device_motion_buffer_ = buffer;
- started_ = DataFetcherImplAndroid::GetInstance()->
- StartFetchingDeviceMotionData(buffer);
- return started_;
+
+ switch (consumer_type) {
+ case CONSUMER_TYPE_MOTION:
+ return DataFetcherImplAndroid::GetInstance()->
+ StartFetchingDeviceMotionData(
+ static_cast<DeviceMotionHardwareBuffer*>(buffer));
+ case CONSUMER_TYPE_ORIENTATION:
+ return DataFetcherImplAndroid::GetInstance()->
+ StartFetchingDeviceOrientationData(
+ static_cast<DeviceOrientationHardwareBuffer*>(buffer));
+ default:
+ NOTREACHED();
+ }
+ return false;
}
-void DataFetcherSharedMemory::StopFetchingDeviceMotionData() {
- DataFetcherImplAndroid::GetInstance()->StopFetchingDeviceMotionData();
- started_ = false;
+bool DataFetcherSharedMemory::Stop(ConsumerType consumer_type) {
+ switch (consumer_type) {
+ case CONSUMER_TYPE_MOTION:
+ DataFetcherImplAndroid::GetInstance()->StopFetchingDeviceMotionData();
+ return true;
+ case CONSUMER_TYPE_ORIENTATION:
+ DataFetcherImplAndroid::GetInstance()->
+ StopFetchingDeviceOrientationData();
+ return true;
+ default:
+ NOTREACHED();
+ }
+ return false;
}
} // 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
new file mode 100644
index 00000000000..429713c781f
--- /dev/null
+++ b/chromium/content/browser/device_orientation/data_fetcher_shared_memory_base.cc
@@ -0,0 +1,247 @@
+// Copyright 2013 The Chromium Authors. All rights 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_shared_memory_base.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#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_orientation_hardware_buffer.h"
+
+namespace content {
+
+namespace {
+const int kPeriodInMilliseconds = 100;
+
+static size_t GetConsumerSharedMemoryBufferSize(ConsumerType consumer_type) {
+ switch (consumer_type) {
+ case CONSUMER_TYPE_MOTION:
+ return sizeof(DeviceMotionHardwareBuffer);
+ case CONSUMER_TYPE_ORIENTATION:
+ return sizeof(DeviceOrientationHardwareBuffer);
+ default:
+ NOTREACHED();
+ }
+ return 0;
+}
+
+}
+
+class DataFetcherSharedMemoryBase::PollingThread : public base::Thread {
+ public:
+ PollingThread(const char* name, DataFetcherSharedMemoryBase* fetcher);
+ virtual ~PollingThread();
+
+ void AddConsumer(ConsumerType consumer_type, void* buffer);
+ void RemoveConsumer(ConsumerType consumer_type);
+
+ unsigned GetConsumersBitmask() const { return consumers_bitmask_; }
+ bool IsTimerRunning() const { return timer_ ? timer_->IsRunning() : false; }
+
+ private:
+
+ void DoPoll();
+
+ unsigned consumers_bitmask_;
+ DataFetcherSharedMemoryBase* fetcher_;
+ base::TimeDelta poll_interval_;
+ scoped_ptr<base::RepeatingTimer<PollingThread> > timer_;
+
+ DISALLOW_COPY_AND_ASSIGN(PollingThread);
+};
+
+// --- PollingThread methods
+
+DataFetcherSharedMemoryBase::PollingThread::PollingThread(
+ const char* name, DataFetcherSharedMemoryBase* fetcher)
+ : base::Thread(name),
+ consumers_bitmask_(0),
+ fetcher_(fetcher),
+ poll_interval_(fetcher->GetPollDelay()) {
+}
+
+DataFetcherSharedMemoryBase::PollingThread::~PollingThread() {
+}
+
+void DataFetcherSharedMemoryBase::PollingThread::AddConsumer(
+ ConsumerType consumer_type, void* buffer) {
+ DCHECK(fetcher_);
+ if (!fetcher_->Start(consumer_type, buffer))
+ return;
+
+ consumers_bitmask_ |= consumer_type;
+
+ if (!timer_ && poll_interval_.InMilliseconds() > 0) {
+ timer_.reset(new base::RepeatingTimer<PollingThread>());
+ timer_->Start(FROM_HERE,
+ poll_interval_,
+ this, &PollingThread::DoPoll);
+ }
+}
+
+void DataFetcherSharedMemoryBase::PollingThread::RemoveConsumer(
+ ConsumerType consumer_type) {
+ DCHECK(fetcher_);
+ if (!fetcher_->Stop(consumer_type))
+ return;
+
+ consumers_bitmask_ ^= consumer_type;
+
+ if (!consumers_bitmask_)
+ timer_.reset(); // will also stop the timer.
+}
+
+void DataFetcherSharedMemoryBase::PollingThread::DoPoll() {
+ DCHECK(fetcher_);
+ DCHECK(consumers_bitmask_);
+ fetcher_->Fetch(consumers_bitmask_);
+}
+
+// --- end of PollingThread methods
+
+DataFetcherSharedMemoryBase::DataFetcherSharedMemoryBase()
+ : started_consumers_(0) {
+}
+
+DataFetcherSharedMemoryBase::~DataFetcherSharedMemoryBase() {
+ StopFetchingDeviceData(CONSUMER_TYPE_MOTION);
+ StopFetchingDeviceData(CONSUMER_TYPE_ORIENTATION);
+
+ // make sure polling thread stops asap.
+ if (polling_thread_)
+ polling_thread_->Stop();
+
+ STLDeleteContainerPairSecondPointers(shared_memory_map_.begin(),
+ shared_memory_map_.end());
+}
+
+bool DataFetcherSharedMemoryBase::StartFetchingDeviceData(
+ ConsumerType consumer_type) {
+ if (started_consumers_ & consumer_type)
+ return true;
+
+ void* buffer = GetSharedMemoryBuffer(consumer_type);
+ if (!buffer)
+ return false;
+
+ if (IsPolling()) {
+ if (!InitAndStartPollingThreadIfNecessary())
+ return false;
+ polling_thread_->message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&PollingThread::AddConsumer,
+ base::Unretained(polling_thread_.get()),
+ consumer_type, buffer));
+ } else {
+ if (!Start(consumer_type, buffer))
+ return false;
+ }
+
+ started_consumers_ |= consumer_type;
+
+ return true;
+}
+
+bool DataFetcherSharedMemoryBase::StopFetchingDeviceData(
+ ConsumerType consumer_type) {
+ if (!(started_consumers_ & consumer_type))
+ return true;
+
+ if (IsPolling()) {
+ polling_thread_->message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&PollingThread::RemoveConsumer,
+ base::Unretained(polling_thread_.get()),
+ consumer_type));
+ } else {
+ if (!Stop(consumer_type))
+ return false;
+ }
+
+ started_consumers_ ^= consumer_type;
+
+ return true;
+}
+
+base::SharedMemoryHandle
+DataFetcherSharedMemoryBase::GetSharedMemoryHandleForProcess(
+ ConsumerType consumer_type, base::ProcessHandle process) {
+ SharedMemoryMap::const_iterator it = shared_memory_map_.find(consumer_type);
+ if (it == shared_memory_map_.end())
+ return base::SharedMemory::NULLHandle();
+
+ base::SharedMemoryHandle renderer_handle;
+ it->second->ShareToProcess(process, &renderer_handle);
+ return renderer_handle;
+}
+
+bool DataFetcherSharedMemoryBase::InitAndStartPollingThreadIfNecessary() {
+ if (polling_thread_)
+ return true;
+
+ polling_thread_.reset(
+ new PollingThread("Inertial Device Sensor poller", this));
+
+ if (!polling_thread_->Start()) {
+ LOG(ERROR) << "Failed to start inertial sensor data polling thread";
+ return false;
+ }
+ return true;
+}
+
+void DataFetcherSharedMemoryBase::Fetch(unsigned consumer_bitmask) {
+ NOTIMPLEMENTED();
+}
+
+bool DataFetcherSharedMemoryBase::IsPolling() const {
+ return false;
+}
+
+base::TimeDelta DataFetcherSharedMemoryBase::GetPollDelay() const {
+ return base::TimeDelta::FromMilliseconds(kPeriodInMilliseconds);
+}
+
+base::SharedMemory* DataFetcherSharedMemoryBase::GetSharedMemory(
+ ConsumerType consumer_type) {
+ SharedMemoryMap::const_iterator it = shared_memory_map_.find(consumer_type);
+ if (it != shared_memory_map_.end())
+ return it->second;
+
+ size_t buffer_size = GetConsumerSharedMemoryBufferSize(consumer_type);
+ if (buffer_size == 0)
+ return NULL;
+
+ scoped_ptr<base::SharedMemory> new_shared_mem(new base::SharedMemory);
+ if (new_shared_mem->CreateAndMapAnonymous(buffer_size)) {
+ if (void* mem = new_shared_mem->memory()) {
+ memset(mem, 0, buffer_size);
+ base::SharedMemory* shared_mem = new_shared_mem.release();
+ shared_memory_map_[consumer_type] = shared_mem;
+ return shared_mem;
+ }
+ }
+ LOG(ERROR) << "Failed to initialize shared memory";
+ return NULL;
+}
+
+void* DataFetcherSharedMemoryBase::GetSharedMemoryBuffer(
+ ConsumerType consumer_type) {
+ if (base::SharedMemory* shared_memory = GetSharedMemory(consumer_type))
+ return shared_memory->memory();
+ return NULL;
+}
+
+base::MessageLoop* DataFetcherSharedMemoryBase::GetPollingMessageLoop() const {
+ return polling_thread_ ? polling_thread_->message_loop() : NULL;
+}
+
+bool DataFetcherSharedMemoryBase::IsPollingTimerRunningForTesting() const {
+ return polling_thread_ ? polling_thread_->IsTimerRunning() : false;
+}
+
+
+} // namespace content
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
new file mode 100644
index 00000000000..8894b014a01
--- /dev/null
+++ b/chromium/content/browser/device_orientation/data_fetcher_shared_memory_base.h
@@ -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.
+
+#ifndef CONTENT_BROWSER_DEVICE_ORIENTATION_DATA_FETCHER_SHARED_MEMORY_BASE_H_
+#define CONTENT_BROWSER_DEVICE_ORIENTATION_DATA_FETCHER_SHARED_MEMORY_BASE_H_
+
+#include <map>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/shared_memory.h"
+#include "base/message_loop/message_loop.h"
+#include "content/browser/device_orientation/inertial_sensor_consts.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+// Sensor data fetchers should derive from this base class and implement
+// the abstract Start() and Stop() methods.
+// If the fetcher requires polling it should also implement IsPolling()
+// to return true and the Fetch() method which will be called from the
+// polling thread to fetch data at regular intervals.
+class CONTENT_EXPORT DataFetcherSharedMemoryBase {
+ public:
+
+ // Starts updating the shared memory buffer with sensor data at
+ // regular intervals. Returns true if the relevant sensors could
+ // be successfully activated.
+ bool StartFetchingDeviceData(ConsumerType consumer_type);
+
+ // Stops updating the shared memory buffer. Returns true if the
+ // relevant sensors could be successfully deactivated.
+ bool StopFetchingDeviceData(ConsumerType consumer_type);
+
+ // Returns the shared memory handle of the device sensor data
+ // duplicated into the given process. This method should only be
+ // called after a call to StartFetchingDeviceData method with
+ // corresponding |consumer_type| parameter.
+ base::SharedMemoryHandle GetSharedMemoryHandleForProcess(
+ ConsumerType consumer_type, base::ProcessHandle process);
+
+ protected:
+ class PollingThread;
+
+ DataFetcherSharedMemoryBase();
+ virtual ~DataFetcherSharedMemoryBase();
+
+ // Returns the message loop of the polling thread.
+ // Returns NULL if there is no polling thread.
+ base::MessageLoop* GetPollingMessageLoop() const;
+
+ // If IsPolling() is true this method is called from the |polling_thread_|
+ // 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 interval between successive calls to Fetch().
+ // If interval is zero, Fetch() is never called.
+ virtual base::TimeDelta GetPollDelay() const;
+
+ // Start() method should call InitSharedMemoryBuffer() to get the shared
+ // memory pointer. If IsPolling() is true both Start() and Stop() methods
+ // are called from the |polling_thread_|.
+ virtual bool Start(ConsumerType consumer_type, void* buffer) = 0;
+ virtual bool Stop(ConsumerType consumer_type) = 0;
+
+ bool IsPollingTimerRunningForTesting() const;
+
+ private:
+ bool InitAndStartPollingThreadIfNecessary();
+ base::SharedMemory* GetSharedMemory(ConsumerType consumer_type);
+ void* GetSharedMemoryBuffer(ConsumerType consumer_type);
+
+ unsigned started_consumers_;
+
+ scoped_ptr<PollingThread> polling_thread_;
+
+ // Owning pointers. Objects in the map are deleted in dtor.
+ typedef std::map<ConsumerType, base::SharedMemory*> SharedMemoryMap;
+ SharedMemoryMap shared_memory_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(DataFetcherSharedMemoryBase);
+};
+
+}
+
+#endif // CONTENT_BROWSER_DEVICE_ORIENTATION_DATA_FETCHER_SHARED_MEMORY_BASE_H_
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
new file mode 100644
index 00000000000..f2028a6c436
--- /dev/null
+++ b/chromium/content/browser/device_orientation/data_fetcher_shared_memory_base_unittest.cc
@@ -0,0 +1,407 @@
+// Copyright 2013 The Chromium Authors. All rights 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_shared_memory_base.h"
+
+#include "base/logging.h"
+#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_orientation_hardware_buffer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+const int kPeriodInMilliseconds = 100;
+
+
+class FakeDataFetcher : public DataFetcherSharedMemoryBase {
+ public:
+ FakeDataFetcher()
+ : start_motion_(false, false),
+ start_orientation_(false, false),
+ stop_motion_(false, false),
+ stop_orientation_(false, false),
+ updated_motion_(false, false),
+ updated_orientation_(false, false),
+ motion_buffer_(NULL),
+ orientation_buffer_(NULL) {
+ }
+ virtual ~FakeDataFetcher() { }
+
+ bool Init(ConsumerType consumer_type, void* buffer) {
+ EXPECT_TRUE(buffer);
+
+ switch (consumer_type) {
+ case CONSUMER_TYPE_MOTION:
+ motion_buffer_ = static_cast<DeviceMotionHardwareBuffer*>(buffer);
+ break;
+ case CONSUMER_TYPE_ORIENTATION:
+ orientation_buffer_ =
+ static_cast<DeviceOrientationHardwareBuffer*>(buffer);
+ break;
+ default:
+ return false;
+ }
+ return true;
+ }
+
+ void UpdateMotion() {
+ DeviceMotionHardwareBuffer* buffer = GetMotionBuffer();
+ ASSERT_TRUE(buffer);
+ buffer->seqlock.WriteBegin();
+ buffer->data.interval = kPeriodInMilliseconds;
+ buffer->seqlock.WriteEnd();
+ updated_motion_.Signal();
+ }
+
+ void UpdateOrientation() {
+ DeviceOrientationHardwareBuffer* buffer = GetOrientationBuffer();
+ ASSERT_TRUE(buffer);
+ buffer->seqlock.WriteBegin();
+ buffer->data.alpha = 1;
+ buffer->seqlock.WriteEnd();
+ updated_orientation_.Signal();
+ }
+
+ DeviceMotionHardwareBuffer* GetMotionBuffer() const {
+ return motion_buffer_;
+ }
+
+ DeviceOrientationHardwareBuffer* GetOrientationBuffer() const {
+ return orientation_buffer_;
+ }
+
+ void WaitForStart(ConsumerType consumer_type) {
+ switch (consumer_type) {
+ case CONSUMER_TYPE_MOTION:
+ start_motion_.Wait();
+ break;
+ case CONSUMER_TYPE_ORIENTATION:
+ start_orientation_.Wait();
+ break;
+ }
+ }
+
+ void WaitForStop(ConsumerType consumer_type) {
+ switch (consumer_type) {
+ case CONSUMER_TYPE_MOTION:
+ stop_motion_.Wait();
+ break;
+ case CONSUMER_TYPE_ORIENTATION:
+ stop_orientation_.Wait();
+ break;
+ }
+ }
+
+ void WaitForUpdate(ConsumerType consumer_type) {
+ switch (consumer_type) {
+ case CONSUMER_TYPE_MOTION:
+ updated_motion_.Wait();
+ break;
+ case CONSUMER_TYPE_ORIENTATION:
+ updated_orientation_.Wait();
+ break;
+ }
+ }
+
+ protected:
+ base::WaitableEvent start_motion_;
+ base::WaitableEvent start_orientation_;
+ base::WaitableEvent stop_motion_;
+ base::WaitableEvent stop_orientation_;
+ base::WaitableEvent updated_motion_;
+ base::WaitableEvent updated_orientation_;
+
+ private:
+ DeviceMotionHardwareBuffer* motion_buffer_;
+ DeviceOrientationHardwareBuffer* orientation_buffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeDataFetcher);
+};
+
+class FakeNonPollingDataFetcher : public FakeDataFetcher {
+ public:
+ FakeNonPollingDataFetcher() { }
+ virtual ~FakeNonPollingDataFetcher() { }
+
+ virtual bool Start(ConsumerType consumer_type, void* buffer) OVERRIDE {
+ Init(consumer_type, buffer);
+ switch (consumer_type) {
+ case CONSUMER_TYPE_MOTION:
+ UpdateMotion();
+ start_motion_.Signal();
+ break;
+ case CONSUMER_TYPE_ORIENTATION:
+ UpdateOrientation();
+ start_orientation_.Signal();
+ break;
+ default:
+ return false;
+ }
+ return true;
+ }
+
+ virtual bool Stop(ConsumerType consumer_type) OVERRIDE {
+ switch (consumer_type) {
+ case CONSUMER_TYPE_MOTION:
+ stop_motion_.Signal();
+ break;
+ case CONSUMER_TYPE_ORIENTATION:
+ stop_orientation_.Signal();
+ break;
+ default:
+ return false;
+ }
+ 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";
+ }
+
+ private:
+
+ DISALLOW_COPY_AND_ASSIGN(FakeNonPollingDataFetcher);
+};
+
+class FakePollingDataFetcher : public FakeDataFetcher {
+ public:
+ FakePollingDataFetcher() { }
+ virtual ~FakePollingDataFetcher() { }
+
+ virtual bool Start(ConsumerType consumer_type, void* buffer) OVERRIDE {
+ EXPECT_TRUE(base::MessageLoop::current() == GetPollingMessageLoop());
+
+ Init(consumer_type, buffer);
+ switch (consumer_type) {
+ case CONSUMER_TYPE_MOTION:
+ start_motion_.Signal();
+ break;
+ case CONSUMER_TYPE_ORIENTATION:
+ start_orientation_.Signal();
+ break;
+ default:
+ return false;
+ }
+ return true;
+ }
+
+ virtual bool Stop(ConsumerType consumer_type) OVERRIDE {
+ EXPECT_TRUE(base::MessageLoop::current() == GetPollingMessageLoop());
+
+ switch (consumer_type) {
+ case CONSUMER_TYPE_MOTION:
+ stop_motion_.Signal();
+ break;
+ case CONSUMER_TYPE_ORIENTATION:
+ stop_orientation_.Signal();
+ break;
+ default:
+ return false;
+ }
+ return true;
+ }
+
+ virtual void Fetch(unsigned consumer_bitmask) OVERRIDE {
+ EXPECT_TRUE(base::MessageLoop::current() == GetPollingMessageLoop());
+ EXPECT_TRUE(consumer_bitmask & CONSUMER_TYPE_ORIENTATION ||
+ consumer_bitmask & CONSUMER_TYPE_MOTION);
+
+ if (consumer_bitmask & CONSUMER_TYPE_ORIENTATION)
+ UpdateOrientation();
+ if (consumer_bitmask & CONSUMER_TYPE_MOTION)
+ UpdateMotion();
+ }
+
+ virtual bool IsPolling() const OVERRIDE {
+ return true;
+ }
+
+ private:
+
+ DISALLOW_COPY_AND_ASSIGN(FakePollingDataFetcher);
+};
+
+class FakeZeroDelayPollingDataFetcher : public FakeDataFetcher {
+ public:
+ FakeZeroDelayPollingDataFetcher() { }
+ virtual ~FakeZeroDelayPollingDataFetcher() { }
+
+ virtual bool Start(ConsumerType consumer_type, void* buffer) OVERRIDE {
+ EXPECT_TRUE(base::MessageLoop::current() == GetPollingMessageLoop());
+
+ Init(consumer_type, buffer);
+ switch (consumer_type) {
+ case CONSUMER_TYPE_MOTION:
+ start_motion_.Signal();
+ break;
+ case CONSUMER_TYPE_ORIENTATION:
+ start_orientation_.Signal();
+ break;
+ default:
+ return false;
+ }
+ return true;
+ }
+
+ virtual bool Stop(ConsumerType consumer_type) OVERRIDE {
+ EXPECT_TRUE(base::MessageLoop::current() == GetPollingMessageLoop());
+
+ switch (consumer_type) {
+ case CONSUMER_TYPE_MOTION:
+ stop_motion_.Signal();
+ break;
+ case CONSUMER_TYPE_ORIENTATION:
+ stop_orientation_.Signal();
+ break;
+ default:
+ return false;
+ }
+ return true;
+ }
+
+ virtual void Fetch(unsigned consumer_bitmask) OVERRIDE {
+ FAIL() << "fetch should not be called";
+ }
+
+ virtual bool IsPolling() const OVERRIDE {
+ return true;
+ }
+
+ virtual base::TimeDelta GetPollDelay() const OVERRIDE {
+ return base::TimeDelta::FromMilliseconds(0);
+ }
+
+ bool IsPollingTimerRunningForTesting() const {
+ return FakeDataFetcher::IsPollingTimerRunningForTesting();
+ }
+
+ private:
+
+ DISALLOW_COPY_AND_ASSIGN(FakeZeroDelayPollingDataFetcher);
+};
+
+
+TEST(DataFetcherSharedMemoryBaseTest, DoesStartMotion) {
+ FakeNonPollingDataFetcher fake_data_fetcher;
+ EXPECT_FALSE(fake_data_fetcher.IsPolling());
+
+ EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(CONSUMER_TYPE_MOTION));
+ fake_data_fetcher.WaitForStart(CONSUMER_TYPE_MOTION);
+
+ EXPECT_EQ(kPeriodInMilliseconds,
+ fake_data_fetcher.GetMotionBuffer()->data.interval);
+
+ fake_data_fetcher.StopFetchingDeviceData(CONSUMER_TYPE_MOTION);
+ fake_data_fetcher.WaitForStop(CONSUMER_TYPE_MOTION);
+}
+
+TEST(DataFetcherSharedMemoryBaseTest, DoesStartOrientation) {
+ FakeNonPollingDataFetcher fake_data_fetcher;
+ EXPECT_FALSE(fake_data_fetcher.IsPolling());
+
+ EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(
+ CONSUMER_TYPE_ORIENTATION));
+ fake_data_fetcher.WaitForStart(CONSUMER_TYPE_ORIENTATION);
+
+ EXPECT_EQ(1, fake_data_fetcher.GetOrientationBuffer()->data.alpha);
+
+ fake_data_fetcher.StopFetchingDeviceData(CONSUMER_TYPE_ORIENTATION);
+ fake_data_fetcher.WaitForStop(CONSUMER_TYPE_ORIENTATION);
+}
+
+TEST(DataFetcherSharedMemoryBaseTest, DoesPollMotion) {
+ FakePollingDataFetcher fake_data_fetcher;
+ EXPECT_TRUE(fake_data_fetcher.IsPolling());
+
+ 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,
+ fake_data_fetcher.GetMotionBuffer()->data.interval);
+
+ fake_data_fetcher.StopFetchingDeviceData(CONSUMER_TYPE_MOTION);
+ fake_data_fetcher.WaitForStop(CONSUMER_TYPE_MOTION);
+}
+
+TEST(DataFetcherSharedMemoryBaseTest, DoesPollOrientation) {
+ FakePollingDataFetcher fake_data_fetcher;
+ EXPECT_TRUE(fake_data_fetcher.IsPolling());
+
+ EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(
+ CONSUMER_TYPE_ORIENTATION));
+ fake_data_fetcher.WaitForStart(CONSUMER_TYPE_ORIENTATION);
+ fake_data_fetcher.WaitForUpdate(CONSUMER_TYPE_ORIENTATION);
+
+ EXPECT_EQ(1, fake_data_fetcher.GetOrientationBuffer()->data.alpha);
+
+ fake_data_fetcher.StopFetchingDeviceData(CONSUMER_TYPE_ORIENTATION);
+ fake_data_fetcher.WaitForStop(CONSUMER_TYPE_ORIENTATION);
+}
+
+TEST(DataFetcherSharedMemoryBaseTest, DoesPollMotionAndOrientation) {
+ FakePollingDataFetcher fake_data_fetcher;
+ EXPECT_TRUE(fake_data_fetcher.IsPolling());
+
+ EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(
+ CONSUMER_TYPE_ORIENTATION));
+ base::SharedMemoryHandle handle_orientation =
+ fake_data_fetcher.GetSharedMemoryHandleForProcess(
+ CONSUMER_TYPE_ORIENTATION, base::GetCurrentProcessHandle());
+ EXPECT_TRUE(base::SharedMemory::IsHandleValid(handle_orientation));
+
+ EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(
+ CONSUMER_TYPE_MOTION));
+ base::SharedMemoryHandle handle_motion =
+ fake_data_fetcher.GetSharedMemoryHandleForProcess(
+ CONSUMER_TYPE_MOTION, base::GetCurrentProcessHandle());
+ EXPECT_TRUE(base::SharedMemory::IsHandleValid(handle_motion));
+
+ fake_data_fetcher.WaitForStart(CONSUMER_TYPE_ORIENTATION);
+ fake_data_fetcher.WaitForStart(CONSUMER_TYPE_MOTION);
+
+ fake_data_fetcher.WaitForUpdate(CONSUMER_TYPE_ORIENTATION);
+ fake_data_fetcher.WaitForUpdate(CONSUMER_TYPE_MOTION);
+
+ EXPECT_EQ(1, fake_data_fetcher.GetOrientationBuffer()->data.alpha);
+ EXPECT_EQ(kPeriodInMilliseconds,
+ fake_data_fetcher.GetMotionBuffer()->data.interval);
+
+ fake_data_fetcher.StopFetchingDeviceData(CONSUMER_TYPE_ORIENTATION);
+ fake_data_fetcher.StopFetchingDeviceData(CONSUMER_TYPE_MOTION);
+ fake_data_fetcher.WaitForStop(CONSUMER_TYPE_ORIENTATION);
+ fake_data_fetcher.WaitForStop(CONSUMER_TYPE_MOTION);
+}
+
+TEST(DataFetcherSharedMemoryBaseTest, DoesNotPollZeroDelay) {
+ FakeZeroDelayPollingDataFetcher fake_data_fetcher;
+ EXPECT_TRUE(fake_data_fetcher.IsPolling());
+ EXPECT_EQ(0, fake_data_fetcher.GetPollDelay().InMilliseconds());
+
+ EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(
+ CONSUMER_TYPE_ORIENTATION));
+ fake_data_fetcher.WaitForStart(CONSUMER_TYPE_ORIENTATION);
+
+ EXPECT_FALSE(fake_data_fetcher.IsPollingTimerRunningForTesting());
+ EXPECT_EQ(0, fake_data_fetcher.GetOrientationBuffer()->data.alpha);
+
+ fake_data_fetcher.StopFetchingDeviceData(CONSUMER_TYPE_ORIENTATION);
+ fake_data_fetcher.WaitForStop(CONSUMER_TYPE_ORIENTATION);
+}
+
+
+
+} // 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 0f66fc79773..c05cdcdbb8f 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
@@ -6,38 +6,67 @@
#include "base/logging.h"
-namespace content {
+namespace {
-DataFetcherSharedMemory::~DataFetcherSharedMemory() {
- if (started_)
- StopFetchingDeviceMotionData();
+static bool SetMotionBuffer(content::DeviceMotionHardwareBuffer* buffer,
+ bool enabled) {
+ if (!buffer)
+ return false;
+ buffer->seqlock.WriteBegin();
+ buffer->data.allAvailableSensorsAreActive = enabled;
+ buffer->seqlock.WriteEnd();
+ return true;
}
-bool DataFetcherSharedMemory::NeedsPolling() {
- return false;
+static bool SetOrientationBuffer(
+ content::DeviceOrientationHardwareBuffer* buffer, bool enabled) {
+ if (!buffer)
+ return false;
+ buffer->seqlock.WriteBegin();
+ buffer->data.allAvailableSensorsAreActive = enabled;
+ buffer->seqlock.WriteEnd();
+ return true;
}
-bool DataFetcherSharedMemory::FetchDeviceMotionDataIntoBuffer() {
- NOTREACHED();
- return false;
}
-bool DataFetcherSharedMemory::StartFetchingDeviceMotionData(
- DeviceMotionHardwareBuffer* buffer) {
+namespace content {
+
+DataFetcherSharedMemory::DataFetcherSharedMemory()
+ : motion_buffer_(NULL), orientation_buffer_(NULL) {
+}
+
+DataFetcherSharedMemory::~DataFetcherSharedMemory() {
+}
+
+bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) {
DCHECK(buffer);
- device_motion_buffer_ = buffer;
- device_motion_buffer_->seqlock.WriteBegin();
- device_motion_buffer_->data.allAvailableSensorsAreActive = true;
- device_motion_buffer_->seqlock.WriteEnd();
- started_ = true;
- return true;
+
+ switch (consumer_type) {
+ case CONSUMER_TYPE_MOTION:
+ motion_buffer_ = static_cast<DeviceMotionHardwareBuffer*>(buffer);
+ return SetMotionBuffer(motion_buffer_, true);
+ case CONSUMER_TYPE_ORIENTATION:
+ orientation_buffer_ =
+ static_cast<DeviceOrientationHardwareBuffer*>(buffer);
+ return SetOrientationBuffer(orientation_buffer_, true);
+ default:
+ NOTREACHED();
+ }
+ return false;
}
-void DataFetcherSharedMemory::StopFetchingDeviceMotionData() {
- device_motion_buffer_->seqlock.WriteBegin();
- device_motion_buffer_->data.allAvailableSensorsAreActive = false;
- device_motion_buffer_->seqlock.WriteEnd();
- started_ = false;
+bool DataFetcherSharedMemory::Stop(ConsumerType consumer_type) {
+
+ switch (consumer_type) {
+ case CONSUMER_TYPE_MOTION:
+ return SetMotionBuffer(motion_buffer_, false);
+ case CONSUMER_TYPE_ORIENTATION:
+ return SetOrientationBuffer(orientation_buffer_, false);
+ default:
+ NOTREACHED();
+ }
+ return false;
}
} // namespace content
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
new file mode 100644
index 00000000000..f606bda3a61
--- /dev/null
+++ b/chromium/content/browser/device_orientation/data_fetcher_shared_memory_mac.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 "data_fetcher_shared_memory.h"
+
+#include "base/logging.h"
+#include "third_party/sudden_motion_sensor/sudden_motion_sensor_mac.h"
+
+namespace {
+
+const double kMeanGravity = 9.80665;
+
+void FetchMotion(SuddenMotionSensor* sensor,
+ content::DeviceMotionHardwareBuffer* buffer) {
+ DCHECK(buffer);
+
+ float axis_value[3];
+ if (!sensor->ReadSensorValues(axis_value))
+ return;
+
+ buffer->seqlock.WriteBegin();
+ buffer->data.accelerationIncludingGravityX = axis_value[0] * kMeanGravity;
+ buffer->data.hasAccelerationIncludingGravityX = true;
+ buffer->data.accelerationIncludingGravityY = axis_value[1] * kMeanGravity;
+ buffer->data.hasAccelerationIncludingGravityY = true;
+ buffer->data.accelerationIncludingGravityZ = axis_value[2] * kMeanGravity;
+ buffer->data.hasAccelerationIncludingGravityZ = true;
+ buffer->data.allAvailableSensorsAreActive = true;
+ buffer->seqlock.WriteEnd();
+}
+
+void FetchOrientation(SuddenMotionSensor* sensor,
+ content::DeviceOrientationHardwareBuffer* buffer) {
+ DCHECK(buffer);
+
+ // Retrieve per-axis calibrated values.
+ float axis_value[3];
+ if (!sensor->ReadSensorValues(axis_value))
+ return;
+
+ // 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;
+ double beta = kRad2deg * atan2(-axis_value[1], axis_value[2]);
+ double 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 (beta == 180.0)
+ beta = -180; // -180 == 180 (upside-down)
+ if (gamma == 90.0)
+ gamma = nextafter(90, 0);
+
+ // At this point, DCHECKing is paranoia. Never hurts.
+ DCHECK_GE(beta, -180.0);
+ DCHECK_LT(beta, 180.0);
+ DCHECK_GE(gamma, -90.0);
+ DCHECK_LT(gamma, 90.0);
+
+ buffer->seqlock.WriteBegin();
+ buffer->data.beta = beta;
+ buffer->data.hasBeta = true;
+ buffer->data.gamma = gamma;
+ buffer->data.hasGamma = true;
+ buffer->data.allAvailableSensorsAreActive = true;
+ buffer->seqlock.WriteEnd();
+}
+
+} // namespace
+
+namespace content {
+
+DataFetcherSharedMemory::DataFetcherSharedMemory() {
+}
+
+DataFetcherSharedMemory::~DataFetcherSharedMemory() {
+}
+
+void DataFetcherSharedMemory::Fetch(unsigned consumer_bitmask) {
+ DCHECK(base::MessageLoop::current() == GetPollingMessageLoop());
+ DCHECK(sudden_motion_sensor_);
+ DCHECK(consumer_bitmask & CONSUMER_TYPE_ORIENTATION ||
+ consumer_bitmask & CONSUMER_TYPE_MOTION);
+
+ if (consumer_bitmask & CONSUMER_TYPE_ORIENTATION)
+ FetchOrientation(sudden_motion_sensor_.get(), orientation_buffer_);
+ if (consumer_bitmask & CONSUMER_TYPE_MOTION)
+ FetchMotion(sudden_motion_sensor_.get(), motion_buffer_);
+}
+
+bool DataFetcherSharedMemory::IsPolling() const {
+ return true;
+}
+
+bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) {
+ DCHECK(base::MessageLoop::current() == GetPollingMessageLoop());
+ DCHECK(buffer);
+
+ switch (consumer_type) {
+ case CONSUMER_TYPE_MOTION:
+ motion_buffer_ = static_cast<DeviceMotionHardwareBuffer*>(buffer);
+ if (!sudden_motion_sensor_)
+ sudden_motion_sensor_.reset(SuddenMotionSensor::Create());
+ 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());
+ return sudden_motion_sensor_.get() != NULL;
+ default:
+ NOTREACHED();
+ }
+ return false;
+}
+
+bool DataFetcherSharedMemory::Stop(ConsumerType consumer_type) {
+ DCHECK(base::MessageLoop::current() == GetPollingMessageLoop());
+
+ switch (consumer_type) {
+ case CONSUMER_TYPE_MOTION:
+ if (motion_buffer_) {
+ motion_buffer_->seqlock.WriteBegin();
+ motion_buffer_->data.allAvailableSensorsAreActive = false;
+ motion_buffer_->seqlock.WriteEnd();
+ motion_buffer_ = NULL;
+ }
+ return true;
+ case CONSUMER_TYPE_ORIENTATION:
+ if (orientation_buffer_) {
+ orientation_buffer_->seqlock.WriteBegin();
+ orientation_buffer_->data.allAvailableSensorsAreActive = false;
+ orientation_buffer_->seqlock.WriteEnd();
+ orientation_buffer_ = NULL;
+ }
+ return true;
+ default:
+ NOTREACHED();
+ }
+ return false;
+}
+
+} // namespace content
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
new file mode 100644
index 00000000000..65389890ee2
--- /dev/null
+++ b/chromium/content/browser/device_orientation/data_fetcher_shared_memory_win.cc
@@ -0,0 +1,394 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "data_fetcher_shared_memory.h"
+
+#include <GuidDef.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"
+
+namespace {
+
+const double kMeanGravity = 9.80665;
+const int kPeriodInMilliseconds = 100;
+
+} // namespace
+
+
+namespace content {
+
+class DataFetcherSharedMemory::SensorEventSink
+ : public ISensorEvents, public base::win::IUnknownImpl {
+ public:
+ SensorEventSink() {}
+ 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 OnLeave(REFSENSOR_ID sensor_id) OVERRIDE {
+ return S_OK;
+ }
+
+ STDMETHODIMP OnStateChanged(ISensor* sensor, SensorState state) OVERRIDE {
+ return S_OK;
+ }
+
+ STDMETHODIMP OnDataUpdated(ISensor* sensor,
+ ISensorDataReport* new_data) OVERRIDE {
+ if (NULL == new_data || NULL == sensor)
+ return E_INVALIDARG;
+ return UpdateSharedMemoryBuffer(sensor, new_data) ? S_OK : E_FAIL;
+ }
+
+protected:
+ virtual bool UpdateSharedMemoryBuffer(
+ ISensor* sensor, ISensorDataReport* new_data) = 0;
+
+ void GetSensorValue(REFPROPERTYKEY property, ISensorDataReport* new_data,
+ double* value, bool* has_value) {
+ PROPVARIANT variant_value = {};
+ if (SUCCEEDED(new_data->GetSensorValue(property, &variant_value))) {
+ if (variant_value.vt == VT_R8)
+ *value = variant_value.dblVal;
+ else if (variant_value.vt == VT_R4)
+ *value = variant_value.fltVal;
+ *has_value = true;
+ } else {
+ *value = 0;
+ *has_value = false;
+ }
+ }
+
+ private:
+
+ DISALLOW_COPY_AND_ASSIGN(SensorEventSink);
+};
+
+class DataFetcherSharedMemory::SensorEventSinkOrientation
+ : public DataFetcherSharedMemory::SensorEventSink {
+ public:
+ explicit SensorEventSinkOrientation(
+ DeviceOrientationHardwareBuffer* const buffer) : buffer_(buffer) {}
+ virtual ~SensorEventSinkOrientation() {}
+
+protected:
+ virtual bool UpdateSharedMemoryBuffer(
+ ISensor* sensor, ISensorDataReport* new_data) OVERRIDE {
+ double alpha, beta, gamma;
+ bool has_alpha, has_beta, has_gamma;
+
+ GetSensorValue(SENSOR_DATA_TYPE_TILT_X_DEGREES, new_data, &alpha,
+ &has_alpha);
+ GetSensorValue(SENSOR_DATA_TYPE_TILT_Y_DEGREES, new_data, &beta,
+ &has_beta);
+ GetSensorValue(SENSOR_DATA_TYPE_TILT_Z_DEGREES, new_data, &gamma,
+ &has_gamma);
+
+ if (buffer_) {
+ buffer_->seqlock.WriteBegin();
+ buffer_->data.alpha = alpha;
+ buffer_->data.hasAlpha = has_alpha;
+ buffer_->data.beta = beta;
+ buffer_->data.hasBeta = has_beta;
+ buffer_->data.gamma = gamma;
+ buffer_->data.hasGamma = has_gamma;
+ buffer_->data.absolute = true;
+ buffer_->data.hasAbsolute = has_alpha || has_beta || has_gamma;
+ buffer_->data.allAvailableSensorsAreActive = true;
+ buffer_->seqlock.WriteEnd();
+ }
+
+ return true;
+ }
+
+ private:
+ DeviceOrientationHardwareBuffer* const buffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(SensorEventSinkOrientation);
+};
+
+class DataFetcherSharedMemory::SensorEventSinkMotion
+ : public DataFetcherSharedMemory::SensorEventSink {
+ public:
+ explicit SensorEventSinkMotion(DeviceMotionHardwareBuffer* const buffer)
+ : buffer_(buffer) {}
+ virtual ~SensorEventSinkMotion() {}
+
+ protected:
+ virtual bool UpdateSharedMemoryBuffer(
+ ISensor* sensor, ISensorDataReport* new_data) OVERRIDE {
+
+ SENSOR_TYPE_ID sensor_type = GUID_NULL;
+ if (!SUCCEEDED(sensor->GetType(&sensor_type)))
+ return false;
+
+ if (IsEqualIID(sensor_type, SENSOR_TYPE_ACCELEROMETER_3D)) {
+ double acceleration_including_gravity_x;
+ double acceleration_including_gravity_y;
+ double acceleration_including_gravity_z;
+ bool has_acceleration_including_gravity_x;
+ bool has_acceleration_including_gravity_y;
+ bool has_acceleration_including_gravity_z;
+
+ GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_X_G, new_data,
+ &acceleration_including_gravity_x,
+ &has_acceleration_including_gravity_x);
+ GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_Y_G, new_data,
+ &acceleration_including_gravity_y,
+ &has_acceleration_including_gravity_y);
+ GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_Z_G, new_data,
+ &acceleration_including_gravity_z,
+ &has_acceleration_including_gravity_z);
+
+ if (buffer_) {
+ buffer_->seqlock.WriteBegin();
+ buffer_->data.accelerationIncludingGravityX =
+ -acceleration_including_gravity_x * kMeanGravity;
+ buffer_->data.hasAccelerationIncludingGravityX =
+ has_acceleration_including_gravity_x;
+ buffer_->data.accelerationIncludingGravityY =
+ -acceleration_including_gravity_y * kMeanGravity;
+ buffer_->data.hasAccelerationIncludingGravityY =
+ has_acceleration_including_gravity_y;
+ buffer_->data.accelerationIncludingGravityZ =
+ -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;
+ buffer_->data.allAvailableSensorsAreActive = true;
+ buffer_->seqlock.WriteEnd();
+ }
+
+ } else if (IsEqualIID(sensor_type, SENSOR_TYPE_GYROMETER_3D)) {
+ double alpha, beta, gamma;
+ bool has_alpha, has_beta, has_gamma;
+
+ GetSensorValue(SENSOR_DATA_TYPE_ANGULAR_VELOCITY_X_DEGREES_PER_SECOND,
+ new_data, &alpha, &has_alpha);
+ GetSensorValue(SENSOR_DATA_TYPE_ANGULAR_VELOCITY_Y_DEGREES_PER_SECOND,
+ new_data, &beta, &has_beta);
+ GetSensorValue(SENSOR_DATA_TYPE_ANGULAR_VELOCITY_Z_DEGREES_PER_SECOND,
+ new_data, &gamma, &has_gamma);
+
+ if (buffer_) {
+ buffer_->seqlock.WriteBegin();
+ buffer_->data.rotationRateAlpha = alpha;
+ buffer_->data.hasRotationRateAlpha = has_alpha;
+ buffer_->data.rotationRateBeta = beta;
+ 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();
+ }
+ }
+
+ return true;
+ }
+
+ private:
+ DeviceMotionHardwareBuffer* const buffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(SensorEventSinkMotion);
+ };
+
+
+DataFetcherSharedMemory::DataFetcherSharedMemory()
+ : motion_buffer_(NULL),
+ orientation_buffer_(NULL) {
+}
+
+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);
+}
+
+bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) {
+ DCHECK(buffer);
+
+ switch (consumer_type) {
+ case CONSUMER_TYPE_ORIENTATION:
+ {
+ orientation_buffer_ =
+ static_cast<DeviceOrientationHardwareBuffer*>(buffer);
+ scoped_refptr<SensorEventSink> sink(
+ new SensorEventSinkOrientation(orientation_buffer_));
+ if (RegisterForSensor(SENSOR_TYPE_INCLINOMETER_3D,
+ sensor_inclinometer_.Receive(), sink))
+ return true;
+ // if no sensors are available set buffer to ready, to fire null-events.
+ SetBufferAvailableState(consumer_type, true);
+ }
+ break;
+ case CONSUMER_TYPE_MOTION:
+ {
+ motion_buffer_ = static_cast<DeviceMotionHardwareBuffer*>(buffer);
+ scoped_refptr<SensorEventSink> sink(
+ new SensorEventSinkMotion(motion_buffer_));
+ bool accelerometer_available = RegisterForSensor(
+ SENSOR_TYPE_ACCELEROMETER_3D, sensor_accelerometer_.Receive(),
+ sink);
+ bool gyrometer_available = RegisterForSensor(
+ SENSOR_TYPE_GYROMETER_3D, sensor_gyrometer_.Receive(), sink);
+ if (accelerometer_available || gyrometer_available)
+ return true;
+ // if no sensors are available set buffer to ready, to fire null-events.
+ SetBufferAvailableState(consumer_type, true);
+ }
+ break;
+ default:
+ NOTREACHED();
+ }
+ return false;
+}
+
+bool DataFetcherSharedMemory::Stop(ConsumerType consumer_type) {
+ DisableSensors(consumer_type);
+ SetBufferAvailableState(consumer_type, false);
+ switch (consumer_type) {
+ case CONSUMER_TYPE_ORIENTATION:
+ orientation_buffer_ = NULL;
+ return true;
+ case CONSUMER_TYPE_MOTION:
+ motion_buffer_ = NULL;
+ return true;
+ default:
+ NOTREACHED();
+ }
+ return false;
+}
+
+bool DataFetcherSharedMemory::RegisterForSensor(
+ REFSENSOR_TYPE_ID sensor_type,
+ ISensor** sensor,
+ scoped_refptr<SensorEventSink> event_sink) {
+ 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, 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);
+ 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());
+ }
+ }
+
+ base::win::ScopedComPtr<ISensorEvents> sensor_events;
+ hr = event_sink->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;
+}
+
+void DataFetcherSharedMemory::DisableSensors(ConsumerType consumer_type) {
+ switch(consumer_type) {
+ case CONSUMER_TYPE_ORIENTATION:
+ if (sensor_inclinometer_) {
+ sensor_inclinometer_->SetEventSink(NULL);
+ sensor_inclinometer_.Release();
+ }
+ break;
+ case CONSUMER_TYPE_MOTION:
+ if (sensor_accelerometer_) {
+ sensor_accelerometer_->SetEventSink(NULL);
+ sensor_accelerometer_.Release();
+ }
+ if (sensor_gyrometer_) {
+ sensor_gyrometer_->SetEventSink(NULL);
+ sensor_gyrometer_.Release();
+ }
+ break;
+ default:
+ NOTREACHED();
+ }
+}
+
+void DataFetcherSharedMemory::SetBufferAvailableState(
+ ConsumerType consumer_type, bool enabled) {
+ switch(consumer_type) {
+ case CONSUMER_TYPE_ORIENTATION:
+ if (orientation_buffer_) {
+ orientation_buffer_->seqlock.WriteBegin();
+ orientation_buffer_->data.allAvailableSensorsAreActive = enabled;
+ orientation_buffer_->seqlock.WriteEnd();
+ }
+ case CONSUMER_TYPE_MOTION:
+ if (motion_buffer_) {
+ motion_buffer_->seqlock.WriteBegin();
+ motion_buffer_->data.allAvailableSensorsAreActive = enabled;
+ motion_buffer_->seqlock.WriteEnd();
+ }
+ default:
+ NOTREACHED();
+ }
+}
+
+} // 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
new file mode 100644
index 00000000000..ee90be16668
--- /dev/null
+++ b/chromium/content/browser/device_orientation/device_inertial_sensor_service.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/browser/device_orientation/device_inertial_sensor_service.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/memory/singleton.h"
+#include "content/browser/device_orientation/data_fetcher_shared_memory.h"
+#include "content/public/browser/render_process_host.h"
+
+namespace content {
+
+DeviceInertialSensorService::DeviceInertialSensorService()
+ : num_motion_readers_(0),
+ num_orientation_readers_(0),
+ is_shutdown_(false) {
+}
+
+DeviceInertialSensorService::~DeviceInertialSensorService() {
+}
+
+DeviceInertialSensorService* DeviceInertialSensorService::GetInstance() {
+ return Singleton<DeviceInertialSensorService,
+ LeakySingletonTraits<DeviceInertialSensorService> >::get();
+}
+
+void DeviceInertialSensorService::AddConsumer(ConsumerType consumer_type) {
+ if (!ChangeNumberConsumers(consumer_type, 1))
+ return;
+
+ DCHECK(GetNumberConsumers(consumer_type));
+
+ if (!data_fetcher_)
+ data_fetcher_.reset(new DataFetcherSharedMemory);
+ data_fetcher_->StartFetchingDeviceData(consumer_type);
+}
+
+void DeviceInertialSensorService::RemoveConsumer(ConsumerType consumer_type) {
+ if (!ChangeNumberConsumers(consumer_type, -1))
+ return;
+
+ if (GetNumberConsumers(consumer_type) == 0)
+ data_fetcher_->StopFetchingDeviceData(consumer_type);
+}
+
+bool DeviceInertialSensorService::ChangeNumberConsumers(
+ ConsumerType consumer_type, int delta) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (is_shutdown_)
+ return false;
+
+ switch (consumer_type) {
+ case CONSUMER_TYPE_MOTION:
+ num_motion_readers_ += delta;
+ DCHECK(num_motion_readers_ >= 0);
+ return true;
+ case CONSUMER_TYPE_ORIENTATION:
+ num_orientation_readers_ += delta;
+ DCHECK(num_orientation_readers_ >= 0);
+ return true;
+ default:
+ NOTREACHED();
+ }
+ return false;
+}
+
+int DeviceInertialSensorService::GetNumberConsumers(
+ ConsumerType consumer_type) const {
+ switch (consumer_type) {
+ case CONSUMER_TYPE_MOTION:
+ return num_motion_readers_;
+ case CONSUMER_TYPE_ORIENTATION:
+ return num_orientation_readers_;
+ default:
+ NOTREACHED();
+ }
+ return 0;
+}
+
+base::SharedMemoryHandle
+DeviceInertialSensorService::GetSharedMemoryHandleForProcess(
+ ConsumerType consumer_type, base::ProcessHandle handle) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return data_fetcher_->GetSharedMemoryHandleForProcess(consumer_type, handle);
+}
+
+void DeviceInertialSensorService::Shutdown() {
+ data_fetcher_.reset();
+ is_shutdown_ = true;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/device_orientation/device_motion_service.h b/chromium/content/browser/device_orientation/device_inertial_sensor_service.h
index 0720bb95968..028d15568ad 100644
--- a/chromium/content/browser/device_orientation/device_motion_service.h
+++ b/chromium/content/browser/device_orientation/device_inertial_sensor_service.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_DEVICE_ORIENTATION_DEVICE_MOTION_SERVICE_H_
-#define CONTENT_BROWSER_DEVICE_ORIENTATION_DEVICE_MOTION_SERVICE_H_
+#ifndef CONTENT_BROWSER_DEVICE_ORIENTATION_DEVICE_INERTIAL_SENSOR_SERVICE_H_
+#define CONTENT_BROWSER_DEVICE_ORIENTATION_DEVICE_INERTIAL_SENSOR_SERVICE_H_
#include "base/basictypes.h"
#include "base/callback_forward.h"
@@ -11,55 +11,58 @@
#include "base/memory/shared_memory.h"
#include "base/memory/singleton.h"
#include "base/threading/thread_checker.h"
+#include "content/browser/device_orientation/inertial_sensor_consts.h"
#include "content/common/content_export.h"
namespace content {
class DataFetcherSharedMemory;
-class DeviceMotionProvider;
class RenderProcessHost;
// Owns the DeviceMotionProvider (the background polling thread) and keeps
// track of the number of consumers currently using the data (and pausing
// the provider when not in use).
-class CONTENT_EXPORT DeviceMotionService {
+class CONTENT_EXPORT DeviceInertialSensorService {
public:
- // Returns the DeviceMotionService singleton.
- static DeviceMotionService* GetInstance();
+ // Returns the DeviceInertialSensorService singleton.
+ static DeviceInertialSensorService* GetInstance();
// Increments the number of users of the provider. The Provider is running
// when there's > 0 users, and is paused when the count drops to 0.
- //
// Must be called on the I/O thread.
- void AddConsumer();
+ void AddConsumer(ConsumerType consumer_type);
// Removes a consumer. Should be matched with an AddConsumer call.
- //
// Must be called on the I/O thread.
- void RemoveConsumer();
+ void RemoveConsumer(ConsumerType cosumer_type);
// Returns the shared memory handle of the device motion data duplicated
// into the given process.
base::SharedMemoryHandle GetSharedMemoryHandleForProcess(
- base::ProcessHandle handle);
+ ConsumerType consumer_type, base::ProcessHandle handle);
- // Stop/join with the background thread in DeviceMotionProvider |provider_|.
+ // Stop/join with the background polling thread in |provider_|.
void Shutdown();
private:
- friend struct DefaultSingletonTraits<DeviceMotionService>;
+ friend struct DefaultSingletonTraits<DeviceInertialSensorService>;
- DeviceMotionService();
- virtual ~DeviceMotionService();
+ DeviceInertialSensorService();
+ virtual ~DeviceInertialSensorService();
- int num_readers_;
+ bool ChangeNumberConsumers(ConsumerType consumer_type,
+ int delta);
+ int GetNumberConsumers(ConsumerType consumer_type) const;
+
+ int num_motion_readers_;
+ int num_orientation_readers_;
bool is_shutdown_;
- scoped_ptr<DeviceMotionProvider> provider_;
+ scoped_ptr<DataFetcherSharedMemory> data_fetcher_;
base::ThreadChecker thread_checker_;
- DISALLOW_COPY_AND_ASSIGN(DeviceMotionService);
+ DISALLOW_COPY_AND_ASSIGN(DeviceInertialSensorService);
};
} // namespace content
-#endif // CONTENT_BROWSER_DEVICE_ORIENTATION_DEVICE_MOTION_SERVICE_H_
+#endif // CONTENT_BROWSER_DEVICE_ORIENTATION_DEVICE_INERTIAL_SENSOR_SERVICE_H_
diff --git a/chromium/content/browser/device_orientation/device_motion_message_filter.cc b/chromium/content/browser/device_orientation/device_motion_message_filter.cc
index 3c619c6cd16..bc33cac3912 100644
--- a/chromium/content/browser/device_orientation/device_motion_message_filter.cc
+++ b/chromium/content/browser/device_orientation/device_motion_message_filter.cc
@@ -4,7 +4,7 @@
#include "content/browser/device_orientation/device_motion_message_filter.h"
-#include "content/browser/device_orientation/device_motion_service.h"
+#include "content/browser/device_orientation/device_inertial_sensor_service.h"
#include "content/common/device_orientation/device_motion_messages.h"
namespace content {
@@ -16,7 +16,8 @@ DeviceMotionMessageFilter::DeviceMotionMessageFilter()
DeviceMotionMessageFilter::~DeviceMotionMessageFilter() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (is_started_)
- DeviceMotionService::GetInstance()->RemoveConsumer();
+ DeviceInertialSensorService::GetInstance()->RemoveConsumer(
+ CONSUMER_TYPE_MOTION);
}
bool DeviceMotionMessageFilter::OnMessageReceived(
@@ -40,7 +41,8 @@ void DeviceMotionMessageFilter::OnDeviceMotionStartPolling() {
if (is_started_)
return;
is_started_ = true;
- DeviceMotionService::GetInstance()->AddConsumer();
+ DeviceInertialSensorService::GetInstance()->AddConsumer(
+ CONSUMER_TYPE_MOTION);
DidStartDeviceMotionPolling();
}
@@ -49,13 +51,15 @@ void DeviceMotionMessageFilter::OnDeviceMotionStopPolling() {
if (!is_started_)
return;
is_started_ = false;
- DeviceMotionService::GetInstance()->RemoveConsumer();
+ DeviceInertialSensorService::GetInstance()->RemoveConsumer(
+ CONSUMER_TYPE_MOTION);
}
void DeviceMotionMessageFilter::DidStartDeviceMotionPolling() {
Send(new DeviceMotionMsg_DidStartPolling(
- DeviceMotionService::GetInstance()->GetSharedMemoryHandleForProcess(
- PeerHandle())));
+ DeviceInertialSensorService::GetInstance()->
+ GetSharedMemoryHandleForProcess(
+ CONSUMER_TYPE_MOTION, PeerHandle())));
}
} // namespace content
diff --git a/chromium/content/browser/device_orientation/device_motion_provider.cc b/chromium/content/browser/device_orientation/device_motion_provider.cc
deleted file mode 100644
index e88d5af83f4..00000000000
--- a/chromium/content/browser/device_orientation/device_motion_provider.cc
+++ /dev/null
@@ -1,172 +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/device_motion_provider.h"
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/threading/thread.h"
-#include "base/timer/timer.h"
-#include "content/browser/device_orientation/data_fetcher_shared_memory.h"
-#include "content/common/device_motion_hardware_buffer.h"
-
-namespace content {
-
-namespace {
-const int kPeriodInMilliseconds = 100;
-}
-
-class DeviceMotionProvider::PollingThread : public base::Thread {
- public:
- explicit PollingThread(const char* name);
- virtual ~PollingThread();
-
- void StartPolling(DataFetcherSharedMemory* fetcher,
- DeviceMotionHardwareBuffer* buffer);
- void StopPolling();
-
- private:
- void DoPoll();
-
- scoped_ptr<base::RepeatingTimer<PollingThread> > timer_;
- DataFetcherSharedMemory* fetcher_;
-
- DISALLOW_COPY_AND_ASSIGN(PollingThread);
-};
-
-// ---- PollingThread methods
-
-DeviceMotionProvider::PollingThread::PollingThread(const char* name)
- : base::Thread(name) {
-}
-
-DeviceMotionProvider::PollingThread::~PollingThread() {
-}
-
-void DeviceMotionProvider::PollingThread::StartPolling(
- DataFetcherSharedMemory* fetcher, DeviceMotionHardwareBuffer* buffer) {
- DCHECK(base::MessageLoop::current() == message_loop());
- DCHECK(!timer_);
-
- fetcher_ = fetcher;
- fetcher_->StartFetchingDeviceMotionData(buffer);
- timer_.reset(new base::RepeatingTimer<PollingThread>());
- timer_->Start(FROM_HERE,
- base::TimeDelta::FromMilliseconds(kPeriodInMilliseconds),
- this, &PollingThread::DoPoll);
-}
-
-void DeviceMotionProvider::PollingThread::StopPolling() {
- DCHECK(base::MessageLoop::current() == message_loop());
- DCHECK(fetcher_);
- // this will also stop the timer before killing it.
- timer_.reset();
- fetcher_->StopFetchingDeviceMotionData();
-}
-
-void DeviceMotionProvider::PollingThread::DoPoll() {
- DCHECK(base::MessageLoop::current() == message_loop());
- fetcher_->FetchDeviceMotionDataIntoBuffer();
-}
-
-// ---- end PollingThread methods
-
-DeviceMotionProvider::DeviceMotionProvider()
- : is_started_(false) {
- Initialize();
-}
-
-DeviceMotionProvider::DeviceMotionProvider(
- scoped_ptr<DataFetcherSharedMemory> fetcher)
- : is_started_(false) {
- data_fetcher_ = fetcher.Pass();
- Initialize();
-}
-
-DeviceMotionProvider::~DeviceMotionProvider() {
- StopFetchingDeviceMotionData();
- // make sure polling thread stops before data_fetcher_ gets deleted.
- if (polling_thread_)
- polling_thread_->Stop();
- data_fetcher_.reset();
-}
-
-void DeviceMotionProvider::Initialize() {
- size_t data_size = sizeof(DeviceMotionHardwareBuffer);
- bool res = device_motion_shared_memory_.CreateAndMapAnonymous(data_size);
- // TODO(timvolodine): consider not crashing the browser if the check fails.
- CHECK(res);
- DeviceMotionHardwareBuffer* hwbuf = SharedMemoryAsHardwareBuffer();
- memset(hwbuf, 0, sizeof(DeviceMotionHardwareBuffer));
-}
-
-base::SharedMemoryHandle DeviceMotionProvider::GetSharedMemoryHandleForProcess(
- base::ProcessHandle process) {
- base::SharedMemoryHandle renderer_handle;
- device_motion_shared_memory_.ShareToProcess(process, &renderer_handle);
- return renderer_handle;
-}
-
-void DeviceMotionProvider::StartFetchingDeviceMotionData() {
- if (is_started_)
- return;
-
- if (!data_fetcher_)
- data_fetcher_.reset(new DataFetcherSharedMemory);
-
- if (data_fetcher_->NeedsPolling()) {
- if (!polling_thread_)
- CreateAndStartPollingThread();
-
- polling_thread_->message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&PollingThread::StartPolling,
- base::Unretained(polling_thread_.get()),
- data_fetcher_.get(),
- SharedMemoryAsHardwareBuffer()));
- } else {
- data_fetcher_->StartFetchingDeviceMotionData(
- SharedMemoryAsHardwareBuffer());
- }
-
- is_started_ = true;
-}
-
-void DeviceMotionProvider::CreateAndStartPollingThread() {
- polling_thread_.reset(
- new PollingThread("Device Motion poller"));
-
- if (!polling_thread_->Start()) {
- LOG(ERROR) << "Failed to start Device Motion data polling thread";
- return;
- }
-}
-
-void DeviceMotionProvider::StopFetchingDeviceMotionData() {
- if (!is_started_)
- return;
-
- DCHECK(data_fetcher_);
-
- if (data_fetcher_->NeedsPolling()) {
- DCHECK(polling_thread_);
- polling_thread_->message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&PollingThread::StopPolling,
- base::Unretained(polling_thread_.get())));
- } else {
- data_fetcher_->StopFetchingDeviceMotionData();
- }
-
- is_started_ = false;
-}
-
-DeviceMotionHardwareBuffer*
-DeviceMotionProvider::SharedMemoryAsHardwareBuffer() {
- void* mem = device_motion_shared_memory_.memory();
- CHECK(mem);
- return static_cast<DeviceMotionHardwareBuffer*>(mem);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/device_orientation/device_motion_provider.h b/chromium/content/browser/device_orientation/device_motion_provider.h
deleted file mode 100644
index 8fd36de33d6..00000000000
--- a/chromium/content/browser/device_orientation/device_motion_provider.h
+++ /dev/null
@@ -1,56 +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_DEVICE_ORIENTATION_DEVICE_MOTION_PROVIDER_H_
-#define CONTENT_BROWSER_DEVICE_ORIENTATION_DEVICE_MOTION_PROVIDER_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/shared_memory.h"
-#include "content/common/content_export.h"
-#include "content/common/device_motion_hardware_buffer.h"
-
-namespace content {
-class DataFetcherSharedMemory;
-
-// This class owns the shared memory buffer for Device Motion and makes
-// sure the data is fetched into that buffer.
-// When DataFetcherSharedMemory::NeedsPolling() is true, it starts a
-// background polling thread to make sure the data is fetched at regular
-// intervals.
-class CONTENT_EXPORT DeviceMotionProvider {
- public:
- DeviceMotionProvider();
-
- // Creates provider with a custom fetcher. Used for testing.
- explicit DeviceMotionProvider(scoped_ptr<DataFetcherSharedMemory> fetcher);
-
- virtual ~DeviceMotionProvider();
-
- // Returns the shared memory handle of the device motion data duplicated
- // into the given process.
- base::SharedMemoryHandle GetSharedMemoryHandleForProcess(
- base::ProcessHandle renderer_process);
-
- void StartFetchingDeviceMotionData();
- void StopFetchingDeviceMotionData();
-
- private:
- class PollingThread;
-
- void Initialize();
- void CreateAndStartPollingThread();
-
- DeviceMotionHardwareBuffer* SharedMemoryAsHardwareBuffer();
-
- base::SharedMemory device_motion_shared_memory_;
- scoped_ptr<DataFetcherSharedMemory> data_fetcher_;
- scoped_ptr<PollingThread> polling_thread_;
- bool is_started_;
-
- DISALLOW_COPY_AND_ASSIGN(DeviceMotionProvider);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_DEVICE_ORIENTATION_DEVICE_MOTION_PROVIDER_H_
diff --git a/chromium/content/browser/device_orientation/device_motion_provider_unittest.cc b/chromium/content/browser/device_orientation/device_motion_provider_unittest.cc
deleted file mode 100644
index cd0f3d843e3..00000000000
--- a/chromium/content/browser/device_orientation/device_motion_provider_unittest.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/browser/device_orientation/device_motion_provider.h"
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/synchronization/waitable_event.h"
-#include "content/browser/device_orientation/data_fetcher_shared_memory.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-namespace {
-
-const int kPeriodInMilliseconds = 100;
-
-class FakeDataFetcherSharedMemory : public DataFetcherSharedMemory {
- public:
- FakeDataFetcherSharedMemory()
- : start_fetching_data_(false, false),
- stop_fetching_data_(false, false),
- fetched_data_(false, false) {
- }
- virtual ~FakeDataFetcherSharedMemory() { }
-
- virtual bool NeedsPolling() OVERRIDE {
- return true;
- }
-
- virtual bool FetchDeviceMotionDataIntoBuffer() OVERRIDE {
- buffer_->seqlock.WriteBegin();
- buffer_->data.interval = kPeriodInMilliseconds;
- buffer_->seqlock.WriteEnd();
- fetched_data_.Signal();
- return true;
- }
-
- virtual bool StartFetchingDeviceMotionData(
- DeviceMotionHardwareBuffer* buffer) OVERRIDE {
- buffer_ = buffer;
- start_fetching_data_.Signal();
- return true;
- }
-
- virtual void StopFetchingDeviceMotionData() OVERRIDE {
- stop_fetching_data_.Signal();
- }
-
- void WaitForStart() {
- start_fetching_data_.Wait();
- }
-
- void WaitForStop() {
- stop_fetching_data_.Wait();
- }
-
- void WaitForDataFetch() {
- fetched_data_.Wait();
- }
-
- DeviceMotionHardwareBuffer* GetBuffer() {
- return buffer_;
- }
-
- private:
- base::WaitableEvent start_fetching_data_;
- base::WaitableEvent stop_fetching_data_;
- base::WaitableEvent fetched_data_;
- DeviceMotionHardwareBuffer* buffer_;
-
- DISALLOW_COPY_AND_ASSIGN(FakeDataFetcherSharedMemory);
-};
-
-
-TEST(DeviceMotionProviderTest, DoesPolling) {
- FakeDataFetcherSharedMemory* mock_data_fetcher =
- new FakeDataFetcherSharedMemory();
- EXPECT_TRUE(mock_data_fetcher->NeedsPolling());
-
- scoped_ptr<DeviceMotionProvider> provider(new DeviceMotionProvider(
- scoped_ptr<DataFetcherSharedMemory>(mock_data_fetcher)));
-
- provider->StartFetchingDeviceMotionData();
- mock_data_fetcher->WaitForStart();
- mock_data_fetcher->WaitForDataFetch();
-
- EXPECT_EQ(kPeriodInMilliseconds,
- mock_data_fetcher->GetBuffer()->data.interval);
-
- provider->StopFetchingDeviceMotionData();
- mock_data_fetcher->WaitForStop();
-}
-
-} // namespace
-
-} // namespace content
diff --git a/chromium/content/browser/device_orientation/device_motion_service.cc b/chromium/content/browser/device_orientation/device_motion_service.cc
deleted file mode 100644
index 48b784b925c..00000000000
--- a/chromium/content/browser/device_orientation/device_motion_service.cc
+++ /dev/null
@@ -1,65 +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/device_motion_service.h"
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/memory/singleton.h"
-#include "content/browser/device_orientation/device_motion_provider.h"
-#include "content/public/browser/render_process_host.h"
-
-namespace content {
-
-DeviceMotionService::DeviceMotionService()
- : num_readers_(0),
- is_shutdown_(false) {
-}
-
-DeviceMotionService::~DeviceMotionService() {
-}
-
-DeviceMotionService* DeviceMotionService::GetInstance() {
- return Singleton<DeviceMotionService,
- LeakySingletonTraits<DeviceMotionService> >::get();
-}
-
-void DeviceMotionService::AddConsumer() {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (is_shutdown_)
- return;
-
- num_readers_++;
- DCHECK(num_readers_ > 0);
- if (!provider_.get())
- provider_.reset(new DeviceMotionProvider);
- provider_->StartFetchingDeviceMotionData();
-}
-
-void DeviceMotionService::RemoveConsumer() {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (is_shutdown_)
- return;
-
- --num_readers_;
- DCHECK(num_readers_ >= 0);
-
- if (num_readers_ == 0) {
- LOG(INFO) << "ACTIVE service stop fetching";
- provider_->StopFetchingDeviceMotionData();
- }
-}
-
-void DeviceMotionService::Shutdown() {
- provider_.reset();
- is_shutdown_ = true;
-}
-
-base::SharedMemoryHandle DeviceMotionService::GetSharedMemoryHandleForProcess(
- base::ProcessHandle handle) {
- DCHECK(thread_checker_.CalledOnValidThread());
- return provider_->GetSharedMemoryHandleForProcess(handle);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/device_orientation/device_orientation_browsertest.cc b/chromium/content/browser/device_orientation/device_orientation_browsertest.cc
index 17d944614d7..92a83c70e0c 100644
--- a/chromium/content/browser/device_orientation/device_orientation_browsertest.cc
+++ b/chromium/content/browser/device_orientation/device_orientation_browsertest.cc
@@ -11,7 +11,7 @@
#include "content/browser/device_orientation/provider.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
-#include "content/shell/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
@@ -71,7 +71,7 @@ IN_PROC_BROWSER_TEST_F(DeviceOrientationBrowserTest, BasicTest) {
// 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()->GetURL().ref());
+ EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
EXPECT_TRUE(provider->added_observer_);
EXPECT_TRUE(provider->removed_observer_);
}
diff --git a/chromium/content/browser/device_orientation/device_orientation_message_filter.cc b/chromium/content/browser/device_orientation/device_orientation_message_filter.cc
index cbb1e674c0e..d00f2b8ccfd 100644
--- a/chromium/content/browser/device_orientation/device_orientation_message_filter.cc
+++ b/chromium/content/browser/device_orientation/device_orientation_message_filter.cc
@@ -4,7 +4,7 @@
#include "content/browser/device_orientation/device_orientation_message_filter.h"
-#include "content/browser/device_orientation/device_motion_service.h"
+#include "content/browser/device_orientation/device_inertial_sensor_service.h"
#include "content/common/device_orientation/device_orientation_messages.h"
namespace content {
@@ -15,10 +15,9 @@ DeviceOrientationMessageFilter::DeviceOrientationMessageFilter()
DeviceOrientationMessageFilter::~DeviceOrientationMessageFilter() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- if (is_started_) {
- // TODO(timvolodine): insert a proper call to DeviceSensorService here,
- // similar to DeviceMotionService::GetInstance()->RemoveConsumer();
- }
+ if (is_started_)
+ DeviceInertialSensorService::GetInstance()->RemoveConsumer(
+ CONSUMER_TYPE_ORIENTATION);
}
bool DeviceOrientationMessageFilter::OnMessageReceived(
@@ -38,33 +37,30 @@ bool DeviceOrientationMessageFilter::OnMessageReceived(
}
void DeviceOrientationMessageFilter::OnDeviceOrientationStartPolling() {
- NOTIMPLEMENTED();
DCHECK(!is_started_);
if (is_started_)
return;
is_started_ = true;
- // TODO(timvolodine): insert a proper call to DeviceSensorService here,
- // similar to DeviceMotionService::GetInstance()->AddConsumer();
+ DeviceInertialSensorService::GetInstance()->AddConsumer(
+ CONSUMER_TYPE_ORIENTATION);
DidStartDeviceOrientationPolling();
}
void DeviceOrientationMessageFilter::OnDeviceOrientationStopPolling() {
- NOTIMPLEMENTED();
DCHECK(is_started_);
if (!is_started_)
return;
is_started_ = false;
- // TODO(timvolodine): insert a proper call to DeviceSensorService here,
- // similar to DeviceMotionService::GetInstance()->RemoveConsumer();
+ DeviceInertialSensorService::GetInstance()->RemoveConsumer(
+ CONSUMER_TYPE_ORIENTATION);
}
void DeviceOrientationMessageFilter::DidStartDeviceOrientationPolling() {
- NOTIMPLEMENTED();
- // TODO(timvolodine): insert a proper call to the generalized Service here,
- // similar to
- // Send(new DeviceOrientationMsg_DidStartPolling(
- // DeviceMotionService::GetInstance()->GetSharedMemoryHandleForProcess(
- // PeerHandle())));
+ Send(new DeviceOrientationMsg_DidStartPolling(
+ DeviceInertialSensorService::GetInstance()->
+ GetSharedMemoryHandleForProcess(
+ CONSUMER_TYPE_ORIENTATION,
+ PeerHandle())));
}
} // namespace content
diff --git a/chromium/content/browser/device_orientation/inertial_sensor_consts.h b/chromium/content/browser/device_orientation/inertial_sensor_consts.h
new file mode 100644
index 00000000000..312b18b1066
--- /dev/null
+++ b/chromium/content/browser/device_orientation/inertial_sensor_consts.h
@@ -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.
+
+#ifndef CONTENT_BROWSER_DEVICE_ORIENTATION_INERTIAL_SENSOR_CONSTS_H_
+#define CONTENT_BROWSER_DEVICE_ORIENTATION_INERTIAL_SENSOR_CONSTS_H_
+
+namespace content {
+
+// Constants related to the Device Motion/Device Orientation APIs.
+
+enum ConsumerType {
+ CONSUMER_TYPE_MOTION = 1 << 0,
+ CONSUMER_TYPE_ORIENTATION = 1 << 1,
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVICE_ORIENTATION_INERTIAL_SENSOR_CONSTS_H_
diff --git a/chromium/content/browser/devtools/browser_protocol.json b/chromium/content/browser/devtools/browser_protocol.json
new file mode 100644
index 00000000000..ecc1bc3624a
--- /dev/null
+++ b/chromium/content/browser/devtools/browser_protocol.json
@@ -0,0 +1,48 @@
+{
+ "version": { "major": "1", "minor": "0" },
+ "domains": [{
+ "domain": "SystemInfo",
+ "description": "The SystemInfo domain defines methods and events for querying low-level system information.",
+ "hidden": true,
+ "types": [
+ {
+ "id": "GPUDevice",
+ "type": "object",
+ "properties": [
+ { "name": "vendorId", "type": "number", "description": "PCI ID of the GPU vendor, if available; 0 otherwise." },
+ { "name": "deviceId", "type": "number", "description": "PCI ID of the GPU device, if available; 0 otherwise." },
+ { "name": "vendorString", "type": "string", "description": "String description of the GPU vendor, if the PCI ID is not available." },
+ { "name": "deviceString", "type": "string", "description": "String description of the GPU device, if the PCI ID is not available." }
+ ],
+ "description": "Describes a single graphics processor (GPU)."
+ },
+ {
+ "id": "GPUInfo",
+ "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." }
+ ],
+ "description": "Provides information about the GPU(s) on the system."
+ },
+ {
+ "id": "SystemInfo",
+ "type": "object",
+ "properties": [
+ { "name": "gpu", "$ref": "GPUInfo", "description": "Information about the GPUs on the system." },
+ { "name": "modelName", "type": "string", "description": "A platform-dependent description of the model of the machine. On Mac OS, this is, for example, 'MacBookPro 10.1'. Will be the empty string if not supported." }
+ ],
+ "description": "Provides information about the system."
+ }
+ ],
+ "commands": [
+ {
+ "name": "getInfo",
+ "description": "Returns information about the system.",
+ "returns": [
+ { "name": "info", "$ref": "SystemInfo", "description": "Information about the system." }
+ ]
+ }
+ ]
+ }]
+}
diff --git a/chromium/content/browser/devtools/devtools_frontend_host.cc b/chromium/content/browser/devtools/devtools_frontend_host.cc
index 8f177b6941c..bfa623a140e 100644
--- a/chromium/content/browser/devtools/devtools_frontend_host.cc
+++ b/chromium/content/browser/devtools/devtools_frontend_host.cc
@@ -63,23 +63,8 @@ bool DevToolsFrontendHost::OnMessageReceived(
IPC_BEGIN_MESSAGE_MAP(DevToolsFrontendHost, message)
IPC_MESSAGE_HANDLER(DevToolsAgentMsg_DispatchOnInspectorBackend,
OnDispatchOnInspectorBackend)
- IPC_MESSAGE_HANDLER(DevToolsHostMsg_ActivateWindow, OnActivateWindow)
- IPC_MESSAGE_HANDLER(DevToolsHostMsg_ChangeAttachedWindowHeight,
- OnChangeAttachedWindowHeight)
- IPC_MESSAGE_HANDLER(DevToolsHostMsg_CloseWindow, OnCloseWindow)
- IPC_MESSAGE_HANDLER(DevToolsHostMsg_MoveWindow, OnMoveWindow)
- IPC_MESSAGE_HANDLER(DevToolsHostMsg_RequestSetDockSide,
- OnRequestSetDockSide)
- IPC_MESSAGE_HANDLER(DevToolsHostMsg_OpenInNewTab, OnOpenInNewTab)
- IPC_MESSAGE_HANDLER(DevToolsHostMsg_Save, OnSave)
- IPC_MESSAGE_HANDLER(DevToolsHostMsg_Append, OnAppend)
- IPC_MESSAGE_HANDLER(DevToolsHostMsg_RequestFileSystems,
- OnRequestFileSystems)
- IPC_MESSAGE_HANDLER(DevToolsHostMsg_AddFileSystem, OnAddFileSystem)
- IPC_MESSAGE_HANDLER(DevToolsHostMsg_RemoveFileSystem, OnRemoveFileSystem)
- IPC_MESSAGE_HANDLER(DevToolsHostMsg_IndexPath, OnIndexPath)
- IPC_MESSAGE_HANDLER(DevToolsHostMsg_StopIndexing, OnStopIndexing)
- IPC_MESSAGE_HANDLER(DevToolsHostMsg_SearchInPath, OnSearchInPath)
+ IPC_MESSAGE_HANDLER(DevToolsHostMsg_DispatchOnEmbedder,
+ OnDispatchOnEmbedder)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -101,72 +86,11 @@ void DevToolsFrontendHost::RenderProcessGone(
void DevToolsFrontendHost::OnDispatchOnInspectorBackend(
const std::string& message) {
DevToolsManagerImpl::GetInstance()->DispatchOnInspectorBackend(this, message);
-// delegate_->DispatchOnInspectorBackend(message);
}
-void DevToolsFrontendHost::OnActivateWindow() {
- delegate_->ActivateWindow();
-}
-
-void DevToolsFrontendHost::OnChangeAttachedWindowHeight(unsigned height) {
- delegate_->ChangeAttachedWindowHeight(height);
-}
-
-void DevToolsFrontendHost::OnCloseWindow() {
- delegate_->CloseWindow();
-}
-
-void DevToolsFrontendHost::OnMoveWindow(int x, int y) {
- delegate_->MoveWindow(x, y);
-}
-
-void DevToolsFrontendHost::OnOpenInNewTab(const std::string& url) {
- delegate_->OpenInNewTab(url);
-}
-
-void DevToolsFrontendHost::OnSave(
- const std::string& url,
- const std::string& content,
- bool save_as) {
- delegate_->SaveToFile(url, content, save_as);
-}
-
-void DevToolsFrontendHost::OnAppend(
- const std::string& url,
- const std::string& content) {
- delegate_->AppendToFile(url, content);
-}
-
-void DevToolsFrontendHost::OnRequestFileSystems() {
- delegate_->RequestFileSystems();
-}
-
-void DevToolsFrontendHost::OnAddFileSystem() {
- delegate_->AddFileSystem();
-}
-
-void DevToolsFrontendHost::OnRemoveFileSystem(
- const std::string& file_system_path) {
- delegate_->RemoveFileSystem(file_system_path);
-}
-
-void DevToolsFrontendHost::OnIndexPath(int request_id,
- const std::string& file_system_path) {
- delegate_->IndexPath(request_id, file_system_path);
-}
-
-void DevToolsFrontendHost::OnStopIndexing(int request_id) {
- delegate_->StopIndexing(request_id);
-}
-
-void DevToolsFrontendHost::OnSearchInPath(int request_id,
- const std::string& file_system_path,
- const std::string& query) {
- delegate_->SearchInPath(request_id, file_system_path, query);
-}
-
-void DevToolsFrontendHost::OnRequestSetDockSide(const std::string& side) {
- delegate_->SetDockSide(side);
+void DevToolsFrontendHost::OnDispatchOnEmbedder(
+ const std::string& message) {
+ delegate_->DispatchOnEmbedder(message);
}
} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_frontend_host.h b/chromium/content/browser/devtools/devtools_frontend_host.h
index 646ea4bbdce..469d162bf9c 100644
--- a/chromium/content/browser/devtools/devtools_frontend_host.h
+++ b/chromium/content/browser/devtools/devtools_frontend_host.h
@@ -40,22 +40,7 @@ class DevToolsFrontendHost : public DevToolsClientHost,
virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE;
void OnDispatchOnInspectorBackend(const std::string& message);
- void OnActivateWindow();
- void OnChangeAttachedWindowHeight(unsigned height);
- void OnCloseWindow();
- void OnMoveWindow(int x, int y);
- void OnRequestSetDockSide(const std::string& side);
- void OnOpenInNewTab(const std::string& url);
- void OnSave(const std::string& url, const std::string& content, bool save_as);
- void OnAppend(const std::string& url, const std::string& content);
- void OnRequestFileSystems();
- void OnAddFileSystem();
- void OnRemoveFileSystem(const std::string& file_system_path);
- void OnIndexPath(int request_id, const std::string& file_system_path);
- void OnStopIndexing(int request_id);
- void OnSearchInPath(int request_id,
- const std::string& file_system_path,
- const std::string& query);
+ void OnDispatchOnEmbedder(const std::string& message);
DevToolsFrontendHostDelegate* delegate_;
DISALLOW_COPY_AND_ASSIGN(DevToolsFrontendHost);
diff --git a/chromium/content/browser/devtools/devtools_http_handler_impl.cc b/chromium/content/browser/devtools/devtools_http_handler_impl.cc
index 47bdfd7b9c8..8003b8bd751 100644
--- a/chromium/content/browser/devtools/devtools_http_handler_impl.cc
+++ b/chromium/content/browser/devtools/devtools_http_handler_impl.cc
@@ -22,6 +22,7 @@
#include "content/browser/devtools/devtools_browser_target.h"
#include "content/browser/devtools/devtools_protocol.h"
#include "content/browser/devtools/devtools_protocol_constants.h"
+#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"
@@ -347,7 +348,7 @@ void DevToolsHttpHandlerImpl::OnHttpRequest(
if (!frontend_dir.empty()) {
base::FilePath path = frontend_dir.AppendASCII(filename);
std::string data;
- file_util::ReadFileToString(path, &data);
+ base::ReadFileToString(path, &data);
server_->Send200(connection_id, data, mime_type);
return;
}
@@ -383,6 +384,10 @@ void DevToolsHttpHandlerImpl::OnWebSocketRequest(
TetheringHandler::kDomain,
new TetheringHandler(delegate_.get()),
false /* handle on this thread */);
+ browser_target_->RegisterDomainHandler(
+ devtools::SystemInfo::kName,
+ new DevToolsSystemInfoHandler(),
+ true /* handle on UI thread */);
server_->AcceptWebSocket(connection_id, request);
return;
diff --git a/chromium/content/browser/devtools/devtools_http_handler_unittest.cc b/chromium/content/browser/devtools/devtools_http_handler_unittest.cc
index e770b8fe455..a57c4ccd4cd 100644
--- a/chromium/content/browser/devtools/devtools_http_handler_unittest.cc
+++ b/chromium/content/browser/devtools/devtools_http_handler_unittest.cc
@@ -23,7 +23,7 @@ class DummyListenSocket : public StreamListenSocket,
// StreamListenSocket::Delegate "implementation"
virtual void DidAccept(StreamListenSocket* server,
- StreamListenSocket* connection) OVERRIDE {}
+ scoped_ptr<StreamListenSocket> connection) OVERRIDE {}
virtual void DidRead(StreamListenSocket* connection,
const char* data,
int len) OVERRIDE {}
@@ -43,11 +43,11 @@ class DummyListenSocketFactory : public net::StreamListenSocketFactory {
BrowserThread::UI, FROM_HERE, quit_closure_2_);
}
- virtual scoped_refptr<StreamListenSocket> CreateAndListen(
+ virtual scoped_ptr<StreamListenSocket> CreateAndListen(
StreamListenSocket::Delegate* delegate) const OVERRIDE {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE, quit_closure_1_);
- return new DummyListenSocket();
+ return scoped_ptr<net::StreamListenSocket>(new DummyListenSocket());
}
private:
base::Closure quit_closure_1_;
@@ -71,10 +71,10 @@ class DummyDelegate : public DevToolsHttpHandlerDelegate {
virtual std::string GetViewDescription(content::RenderViewHost*) OVERRIDE {
return std::string();
}
- virtual scoped_refptr<net::StreamListenSocket> CreateSocketForTethering(
+ virtual scoped_ptr<net::StreamListenSocket> CreateSocketForTethering(
net::StreamListenSocket::Delegate* delegate,
std::string* name) OVERRIDE {
- return NULL;
+ return scoped_ptr<net::StreamListenSocket>();
}
};
diff --git a/chromium/content/browser/devtools/devtools_protocol.cc b/chromium/content/browser/devtools/devtools_protocol.cc
index 83980846556..948ed6be8a4 100644
--- a/chromium/content/browser/devtools/devtools_protocol.cc
+++ b/chromium/content/browser/devtools/devtools_protocol.cc
@@ -190,6 +190,11 @@ void DevToolsProtocol::Handler::SendNotification(
SendRawMessage(notification->Serialize());
}
+void DevToolsProtocol::Handler::SendAsyncResponse(
+ scoped_refptr<DevToolsProtocol::Response> response) {
+ SendRawMessage(response->Serialize());
+}
+
void DevToolsProtocol::Handler::SendRawMessage(const std::string& message) {
if (!notifier_.is_null())
notifier_.Run(message);
diff --git a/chromium/content/browser/devtools/devtools_protocol.h b/chromium/content/browser/devtools/devtools_protocol.h
index 0012947382c..2f7ce0bfecb 100644
--- a/chromium/content/browser/devtools/devtools_protocol.h
+++ b/chromium/content/browser/devtools/devtools_protocol.h
@@ -141,6 +141,8 @@ class DevToolsProtocol {
void SendNotification(const std::string& method,
base::DictionaryValue* params);
+ void SendAsyncResponse(scoped_refptr<DevToolsProtocol::Response> response);
+
// Sends message to client, the caller is presumed to properly
// format the message.
void SendRawMessage(const std::string& message);
diff --git a/chromium/content/browser/devtools/devtools_protocol_constants.cc b/chromium/content/browser/devtools/devtools_protocol_constants.cc
index c689ea1b7cb..d9c337fc8aa 100644
--- a/chromium/content/browser/devtools/devtools_protocol_constants.cc
+++ b/chromium/content/browser/devtools/devtools_protocol_constants.cc
@@ -7,46 +7,132 @@
namespace content {
namespace devtools {
+const char kParamX[] = "x";
+const char kParamY[] = "y";
+const char kParamWidth[] = "width";
+const char kParamHeight[] = "height";
+
+namespace DOM {
+
+namespace setFileInputFiles {
+ const char kName[] = "DOM.setFileInputFiles";
+ const char kParamFiles[] = "files";
+} // 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
+
namespace Inspector {
+
namespace detached {
const char kName[] = "Inspector.detached";
const char kParamReason[] = "reason";
} // detached
+
namespace targetCrashed {
const char kName[] = "Inspector.targetCrashed";
} // targetCrashed
-} // Inspector
-namespace DOM {
-namespace setFileInputFiles {
- const char kName[] = "DOM.setFileInputFiles";
- const char kParamFiles[] = "files";
-} // setFileInputFiles
-} // DOM
+} // Inspector
namespace 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 kParamScale[] = "scale";
- const char kResponseData[] = "data";
+ 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
+
} // Worker
namespace Tracing {
@@ -70,8 +156,17 @@ namespace dataCollected {
const char kName[] = "Tracing.dataCollected";
const char kValue[] = "value";
}
+
} // Tracing
+namespace SystemInfo {
+ const char kName[] = "SystemInfo";
+
+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 a05493318e1..733e697189c 100644
--- a/chromium/content/browser/devtools/devtools_protocol_constants.h
+++ b/chromium/content/browser/devtools/devtools_protocol_constants.h
@@ -14,72 +14,168 @@
namespace content {
namespace devtools {
-namespace Inspector {
-namespace detached {
- extern const char kName[];
- extern const char kParamReason[];
-} // detached
-namespace targetCrashed {
- extern const char kName[];
-} // targetCrashed
-} // Inspector
+extern const char kParamX[];
+extern const char kParamY[];
+extern const char kParamWidth[];
+extern const char kParamHeight[];
namespace DOM {
-namespace setFileInputFiles {
- extern const char kName[];
- extern const char kParamFiles[];
-} // setFileInputFiles
+
+ namespace setFileInputFiles {
+ extern const char kName[];
+ extern const char kParamFiles[];
+ } // 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
+
+ namespace dispatchGestureEvent {
+ extern const char kName[];
+ extern const char kParamDeltaX[];
+ extern const char kParamDeltaY[];
+ extern const char kParamPinchScale[];
+ } // dispatchGestureEvent
+
+} // Input
+
+namespace Inspector {
+
+ namespace detached {
+ extern const char kName[];
+ extern const char kParamReason[];
+ } // detached
+
+ namespace targetCrashed {
+ extern const char kName[];
+ } // targetCrashed
+
+} // Inspector
+
namespace Page {
-namespace handleJavaScriptDialog {
- extern const char kName[];
- extern const char kParamAccept[];
- extern const char kParamPromptText[];
-} // handleJavaScriptDialog
-namespace navigate {
- extern const char kName[];
- extern const char kParamUrl[];
-} // navigate
-namespace captureScreenshot {
- extern const char kName[];
- extern const char kParamFormat[];
- extern const char kParamQuality[];
- extern const char kParamScale[];
- extern const char kResponseData[];
-} // captureScreenshot
+
+ 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 disable {
+ extern const char kName[];
+ } // disable
+
+ namespace handleJavaScriptDialog {
+ extern const char kName[];
+ extern const char kParamAccept[];
+ extern const char kParamPromptText[];
+ } // handleJavaScriptDialog
+
+ namespace navigate {
+ extern const char kName[];
+ extern const char kParamUrl[];
+ } // navigate
+
+ namespace reload {
+ extern const char kName[];
+ } // reload
+
+ namespace getNavigationHistory {
+ 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
+
+ namespace navigateToHistoryEntry {
+ extern const char kName[];
+ extern const char kParamEntryId[];
+ } // navigateToHistoryEntry
+
+ namespace captureScreenshot {
+ extern const char kName[];
+ extern const char kParamFormat[];
+ extern const char kParamQuality[];
+ extern const char kParamMaxWidth[];
+ extern const char kParamMaxHeight[];
+ } // captureScreenshot
+
+ namespace startScreencast {
+ extern const char kName[];
+ } // startScreencast
+
+ namespace stopScreencast {
+ extern const char kName[];
+ } // stopScreencast
+
+ namespace screencastFrame {
+ extern const char kName[];
+ } // screencastFrame
+
+ namespace screencastVisibilityChanged {
+ extern const char kName[];
+ extern const char kParamVisible[];
+ } // screencastVisibilityChanged
} // Page
namespace Tracing {
extern const char kName[];
-namespace start {
- extern const char kName[];
- extern const char kCategories[];
- extern const char kTraceOptions[];
-} // start
+ namespace start {
+ extern const char kName[];
+ extern const char kCategories[];
+ extern const char kTraceOptions[];
+ } // start
-namespace end {
- extern const char kName[];
-}
+ namespace end {
+ extern const char kName[];
+ }
-namespace tracingComplete {
- extern const char kName[];
-}
+ namespace tracingComplete {
+ extern const char kName[];
+ }
-namespace dataCollected {
- extern const char kName[];
- extern const char kValue[];
-}
-} // Tracing
+ namespace dataCollected {
+ extern const char kName[];
+ extern const char kValue[];
+ }
+} // Tracing
namespace Worker {
-namespace disconnectedFromWorker {
- extern const char kName[];
-} // disconnectedFromWorker
+
+ namespace disconnectedFromWorker {
+ extern const char kName[];
+ } // disconnectedFromWorker
+
} // Worker
+
+namespace SystemInfo {
+ extern const char kName[];
+
+namespace getInfo {
+ extern const char kName[];
+} // getInfo
+} // SystemInfo
+
} // devtools
} // content
diff --git a/chromium/content/browser/devtools/devtools_system_info_handler.cc b/chromium/content/browser/devtools/devtools_system_info_handler.cc
new file mode 100644
index 00000000000..1fee6424676
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_system_info_handler.cc
@@ -0,0 +1,123 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/devtools/devtools_system_info_handler.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/values.h"
+#include "content/browser/devtools/devtools_protocol_constants.h"
+#include "content/browser/gpu/gpu_data_manager_impl.h"
+#include "gpu/config/gpu_info.h"
+
+namespace content {
+
+namespace {
+
+const char kAuxAttributes[] = "auxAttributes";
+const char kDeviceId[] = "deviceId";
+const char kDeviceString[] = "deviceString";
+const char kDevices[] = "devices";
+const char kGPU[] = "gpu";
+const char kModelName[] = "modelName";
+const char kVendorId[] = "vendorId";
+const char kVendorString[] = "vendorString";
+
+class AuxGPUInfoEnumerator : public gpu::GPUInfo::Enumerator {
+ public:
+ AuxGPUInfoEnumerator(base::DictionaryValue* dictionary)
+ : dictionary_(dictionary),
+ in_aux_attributes_(false) { }
+
+ virtual void AddInt64(const char* name, int64 value) OVERRIDE {
+ if (in_aux_attributes_)
+ dictionary_->SetDouble(name, value);
+ }
+
+ virtual void AddInt(const char* name, int value) OVERRIDE {
+ if (in_aux_attributes_)
+ dictionary_->SetInteger(name, value);
+ }
+
+ virtual void AddString(const char* name, const std::string& value) OVERRIDE {
+ if (in_aux_attributes_)
+ dictionary_->SetString(name, value);
+ }
+
+ virtual void AddBool(const char* name, bool value) OVERRIDE {
+ if (in_aux_attributes_)
+ dictionary_->SetBoolean(name, value);
+ }
+
+ virtual void AddTimeDeltaInSecondsF(const char* name,
+ const base::TimeDelta& value) OVERRIDE {
+ if (in_aux_attributes_)
+ dictionary_->SetDouble(name, value.InSecondsF());
+ }
+
+ virtual void BeginGPUDevice() OVERRIDE {
+ }
+
+ virtual void EndGPUDevice() OVERRIDE {
+ }
+
+ virtual void BeginAuxAttributes() OVERRIDE {
+ in_aux_attributes_ = true;
+ }
+
+ virtual void EndAuxAttributes() OVERRIDE {
+ in_aux_attributes_ = false;
+ }
+
+ private:
+ base::DictionaryValue* dictionary_;
+ bool in_aux_attributes_;
+};
+
+base::DictionaryValue* GPUDeviceToDictionary(
+ const gpu::GPUInfo::GPUDevice& device) {
+ base::DictionaryValue* result = new base::DictionaryValue;
+ result->SetInteger(kVendorId, device.vendor_id);
+ result->SetInteger(kDeviceId, device.device_id);
+ result->SetString(kVendorString, device.vendor_string);
+ result->SetString(kDeviceString, device.device_string);
+ return result;
+}
+
+} // namespace
+
+DevToolsSystemInfoHandler::DevToolsSystemInfoHandler() {
+ RegisterCommandHandler(devtools::SystemInfo::getInfo::kName,
+ base::Bind(&DevToolsSystemInfoHandler::OnGetInfo,
+ base::Unretained(this)));
+}
+
+DevToolsSystemInfoHandler::~DevToolsSystemInfoHandler() {
+}
+
+scoped_refptr<DevToolsProtocol::Response>
+DevToolsSystemInfoHandler::OnGetInfo(
+ scoped_refptr<DevToolsProtocol::Command> command) {
+ gpu::GPUInfo gpu_info = GpuDataManagerImpl::GetInstance()->GetGPUInfo();
+ base::DictionaryValue* gpu_dict = new base::DictionaryValue;
+
+ base::ListValue* devices = new base::ListValue;
+ devices->Append(GPUDeviceToDictionary(gpu_info.gpu));
+ for (size_t ii = 0; ii < gpu_info.secondary_gpus.size(); ++ii) {
+ devices->Append(GPUDeviceToDictionary(gpu_info.secondary_gpus[ii]));
+ }
+ gpu_dict->Set(kDevices, devices);
+
+ base::DictionaryValue* aux_attributes = new base::DictionaryValue;
+ AuxGPUInfoEnumerator enumerator(aux_attributes);
+ gpu_info.EnumerateFields(&enumerator);
+ gpu_dict->Set(kAuxAttributes, aux_attributes);
+
+ base::DictionaryValue* system_dict = new base::DictionaryValue;
+ system_dict->SetString(kModelName, gpu_info.machine_model);
+ system_dict->Set(kGPU, gpu_dict);
+ return command->SuccessResponse(system_dict);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_system_info_handler.h b/chromium/content/browser/devtools/devtools_system_info_handler.h
new file mode 100644
index 00000000000..afaf042b5b6
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_system_info_handler.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_BROWSER_DEVTOOLS_DEVTOOLS_SYSTEM_INFO_HANDLER_H_
+#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_SYSTEM_INFO_HANDLER_H_
+
+#include "content/browser/devtools/devtools_protocol.h"
+
+namespace content {
+
+// This class provides information to DevTools about the system it's running on.
+class DevToolsSystemInfoHandler
+ : public DevToolsProtocol::Handler {
+ public:
+ DevToolsSystemInfoHandler();
+ virtual ~DevToolsSystemInfoHandler();
+
+ private:
+ scoped_refptr<DevToolsProtocol::Response> OnGetInfo(
+ scoped_refptr<DevToolsProtocol::Command> command);
+
+ DISALLOW_COPY_AND_ASSIGN(DevToolsSystemInfoHandler);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_SYSTEM_INFO_HANDLER_H_
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 7455c160d8e..5570ee839ed 100644
--- a/chromium/content/browser/devtools/render_view_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/render_view_devtools_agent_host.cc
@@ -17,9 +17,11 @@
#include "content/browser/site_instance_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/devtools_messages.h"
+#include "content/common/view_messages.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_widget_host_iterator.h"
namespace content {
@@ -100,15 +102,16 @@ bool DevToolsAgentHost::IsDebuggerAttached(WebContents* web_contents) {
//static
std::vector<RenderViewHost*> DevToolsAgentHost::GetValidRenderViewHosts() {
std::vector<RenderViewHost*> result;
- RenderWidgetHost::List widgets = RenderWidgetHost::GetRenderWidgetHosts();
- for (size_t i = 0; i < widgets.size(); ++i) {
+ scoped_ptr<RenderWidgetHostIterator> widgets(
+ RenderWidgetHost::GetRenderWidgetHosts());
+ while (RenderWidgetHost* widget = widgets->GetNextHost()) {
// Ignore processes that don't have a connection, such as crashed contents.
- if (!widgets[i]->GetProcess()->HasConnection())
+ if (!widget->GetProcess()->HasConnection())
continue;
- if (!widgets[i]->IsRenderView())
+ if (!widget->IsRenderView())
continue;
- RenderViewHost* rvh = RenderViewHost::From(widgets[i]);
+ RenderViewHost* rvh = RenderViewHost::From(widget);
WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
// Don't report a RenderViewHost if it is not the current RenderViewHost
// for some WebContents.
@@ -133,7 +136,8 @@ void RenderViewDevToolsAgentHost::OnCancelPendingNavigation(
RenderViewDevToolsAgentHost::RenderViewDevToolsAgentHost(
RenderViewHost* rvh)
- : overrides_handler_(new RendererOverridesHandler(this)),
+ : render_view_host_(NULL),
+ overrides_handler_(new RendererOverridesHandler(this)),
tracing_handler_(new DevToolsTracingHandler())
{
SetRenderViewHost(rvh);
@@ -145,7 +149,7 @@ RenderViewDevToolsAgentHost::RenderViewDevToolsAgentHost(
g_instances.Get().push_back(this);
RenderViewHostDelegate* delegate = render_view_host_->GetDelegate();
if (delegate && delegate->GetAsWebContents())
- Observe(delegate->GetAsWebContents());
+ WebContentsObserver::Observe(delegate->GetAsWebContents());
AddRef(); // Balanced in RenderViewHostDestroyed.
}
@@ -194,6 +198,11 @@ void RenderViewDevToolsAgentHost::OnClientAttached() {
}
void RenderViewDevToolsAgentHost::OnClientDetached() {
+ overrides_handler_->OnClientDetached();
+ ClientDetachedFromRenderer();
+}
+
+void RenderViewDevToolsAgentHost::ClientDetachedFromRenderer() {
if (!render_view_host_)
return;
@@ -266,9 +275,33 @@ void RenderViewDevToolsAgentHost::DidAttachInterstitialPage() {
ConnectRenderViewHost(web_contents->GetRenderViewHost());
}
+void RenderViewDevToolsAgentHost::Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ if (type == content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED) {
+ bool visible = *Details<bool>(details).ptr();
+ overrides_handler_->OnVisibilityChanged(visible);
+ }
+}
+
void RenderViewDevToolsAgentHost::SetRenderViewHost(RenderViewHost* rvh) {
+ DCHECK(!render_view_host_);
render_view_host_ = rvh;
rvh_observer_.reset(new DevToolsAgentHostRvhObserver(rvh, this));
+ registrar_.Add(
+ this,
+ content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
+ content::Source<RenderWidgetHost>(render_view_host_));
+}
+
+void RenderViewDevToolsAgentHost::ClearRenderViewHost() {
+ DCHECK(render_view_host_);
+ registrar_.Remove(
+ this,
+ content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
+ content::Source<RenderWidgetHost>(render_view_host_));
+ rvh_observer_.reset(NULL);
+ render_view_host_ = NULL;
}
void RenderViewDevToolsAgentHost::ConnectRenderViewHost(RenderViewHost* rvh) {
@@ -278,9 +311,8 @@ void RenderViewDevToolsAgentHost::ConnectRenderViewHost(RenderViewHost* rvh) {
}
void RenderViewDevToolsAgentHost::DisconnectRenderViewHost() {
- OnClientDetached();
- rvh_observer_.reset();
- render_view_host_ = NULL;
+ ClientDetachedFromRenderer();
+ ClearRenderViewHost();
}
void RenderViewDevToolsAgentHost::RenderViewHostDestroyed(
@@ -288,7 +320,7 @@ void RenderViewDevToolsAgentHost::RenderViewHostDestroyed(
DCHECK(render_view_host_);
scoped_refptr<RenderViewDevToolsAgentHost> protect(this);
NotifyCloseListener();
- render_view_host_ = NULL;
+ ClearRenderViewHost();
Release();
}
@@ -301,9 +333,9 @@ void RenderViewDevToolsAgentHost::RenderViewCrashed() {
}
bool RenderViewDevToolsAgentHost::OnRvhMessageReceived(
- const IPC::Message& message) {
+ const IPC::Message& msg) {
bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(RenderViewDevToolsAgentHost, message)
+ IPC_BEGIN_MESSAGE_MAP(RenderViewDevToolsAgentHost, msg)
IPC_MESSAGE_HANDLER(DevToolsClientMsg_DispatchOnInspectorFrontend,
OnDispatchOnInspectorFrontend)
IPC_MESSAGE_HANDLER(DevToolsHostMsg_SaveAgentRuntimeState,
@@ -311,11 +343,18 @@ bool RenderViewDevToolsAgentHost::OnRvhMessageReceived(
IPC_MESSAGE_HANDLER(DevToolsHostMsg_ClearBrowserCache, OnClearBrowserCache)
IPC_MESSAGE_HANDLER(DevToolsHostMsg_ClearBrowserCookies,
OnClearBrowserCookies)
+ IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_SwapCompositorFrame,
+ handled = false; OnSwapCompositorFrame(msg))
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
+void RenderViewDevToolsAgentHost::OnSwapCompositorFrame(
+ const IPC::Message& message) {
+ overrides_handler_->OnSwapCompositorFrame(message);
+}
+
void RenderViewDevToolsAgentHost::OnSaveAgentRuntimeState(
const std::string& state) {
if (!render_view_host_)
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 00f73a6b2a0..3f763cabb36 100644
--- a/chromium/content/browser/devtools/render_view_devtools_agent_host.h
+++ b/chromium/content/browser/devtools/render_view_devtools_agent_host.h
@@ -12,6 +12,8 @@
#include "base/memory/scoped_ptr.h"
#include "content/browser/devtools/ipc_devtools_agent_host.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_view_host_observer.h"
#include "content/public/browser/web_contents_observer.h"
@@ -23,7 +25,8 @@ class RenderViewHost;
class CONTENT_EXPORT RenderViewDevToolsAgentHost
: public IPCDevToolsAgentHost,
- private WebContentsObserver {
+ private WebContentsObserver,
+ public NotificationObserver {
public:
static void OnCancelPendingNavigation(RenderViewHost* pending,
RenderViewHost* current);
@@ -54,22 +57,32 @@ class CONTENT_EXPORT RenderViewDevToolsAgentHost
virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE;
virtual void DidAttachInterstitialPage() OVERRIDE;
+ // NotificationObserver overrides:
+ virtual void Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) OVERRIDE;
+
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);
void OnSaveAgentRuntimeState(const std::string& state);
void OnClearBrowserCache();
void OnClearBrowserCookies();
+ void ClientDetachedFromRenderer();
+
RenderViewHost* render_view_host_;
scoped_ptr<DevToolsAgentHostRvhObserver> rvh_observer_;
scoped_ptr<RendererOverridesHandler> overrides_handler_;
scoped_ptr<DevToolsTracingHandler> tracing_handler_;
std::string state_;
+ NotificationRegistrar registrar_;
DISALLOW_COPY_AND_ASSIGN(RenderViewDevToolsAgentHost);
};
diff --git a/chromium/content/browser/devtools/renderer_overrides_handler.cc b/chromium/content/browser/devtools/renderer_overrides_handler.cc
index 57266676e87..c25adde7619 100644
--- a/chromium/content/browser/devtools/renderer_overrides_handler.cc
+++ b/chromium/content/browser/devtools/renderer_overrides_handler.cc
@@ -15,12 +15,16 @@
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/devtools/devtools_protocol_constants.h"
#include "content/browser/devtools/devtools_tracing_handler.h"
+#include "content/browser/renderer_host/dip_util.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
+#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/common/view_messages.h"
#include "content/port/browser/render_widget_host_view_port.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/javascript_dialog_manager.h"
#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
@@ -28,23 +32,47 @@
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/common/page_transition_types.h"
#include "content/public/common/referrer.h"
+#include "ipc/ipc_sender.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"
-using base::TimeTicks;
+using WebKit::WebGestureEvent;
+using WebKit::WebInputEvent;
+using WebKit::WebMouseEvent;
+
+namespace content {
namespace {
static const char kPng[] = "png";
static const char kJpeg[] = "jpeg";
static int kDefaultScreenshotQuality = 80;
+static int kFrameRateThresholdMs = 100;
-} // namespace
+void ParseGenericInputParams(base::DictionaryValue* params,
+ WebInputEvent* event) {
+ int modifiers = 0;
+ if (params->GetInteger(devtools::Input::kParamModifiers,
+ &modifiers)) {
+ if (modifiers & 1)
+ event->modifiers |= WebInputEvent::AltKey;
+ if (modifiers & 2)
+ event->modifiers |= WebInputEvent::ControlKey;
+ if (modifiers & 4)
+ event->modifiers |= WebInputEvent::MetaKey;
+ if (modifiers & 8)
+ event->modifiers |= WebInputEvent::ShiftKey;
+ }
-namespace content {
+ params->GetDouble(devtools::Input::kParamTimestamp,
+ &event->timeStampSeconds);
+}
+
+} // namespace
RendererOverridesHandler::RendererOverridesHandler(DevToolsAgentHost* agent)
: agent_(agent),
@@ -55,6 +83,10 @@ RendererOverridesHandler::RendererOverridesHandler(DevToolsAgentHost* agent)
&RendererOverridesHandler::GrantPermissionsForSetFileInputFiles,
base::Unretained(this)));
RegisterCommandHandler(
+ devtools::Page::disable::kName,
+ base::Bind(
+ &RendererOverridesHandler::PageDisable, base::Unretained(this)));
+ RegisterCommandHandler(
devtools::Page::handleJavaScriptDialog::kName,
base::Bind(
&RendererOverridesHandler::PageHandleJavaScriptDialog,
@@ -65,14 +97,141 @@ RendererOverridesHandler::RendererOverridesHandler(DevToolsAgentHost* agent)
&RendererOverridesHandler::PageNavigate,
base::Unretained(this)));
RegisterCommandHandler(
+ devtools::Page::reload::kName,
+ base::Bind(
+ &RendererOverridesHandler::PageReload,
+ base::Unretained(this)));
+ RegisterCommandHandler(
+ devtools::Page::getNavigationHistory::kName,
+ base::Bind(
+ &RendererOverridesHandler::PageGetNavigationHistory,
+ base::Unretained(this)));
+ RegisterCommandHandler(
+ devtools::Page::navigateToHistoryEntry::kName,
+ base::Bind(
+ &RendererOverridesHandler::PageNavigateToHistoryEntry,
+ base::Unretained(this)));
+ RegisterCommandHandler(
devtools::Page::captureScreenshot::kName,
base::Bind(
&RendererOverridesHandler::PageCaptureScreenshot,
base::Unretained(this)));
+ RegisterCommandHandler(
+ devtools::Page::startScreencast::kName,
+ base::Bind(
+ &RendererOverridesHandler::PageStartScreencast,
+ base::Unretained(this)));
+ RegisterCommandHandler(
+ devtools::Page::stopScreencast::kName,
+ base::Bind(
+ &RendererOverridesHandler::PageStopScreencast,
+ base::Unretained(this)));
+ RegisterCommandHandler(
+ devtools::Input::dispatchMouseEvent::kName,
+ base::Bind(
+ &RendererOverridesHandler::InputDispatchMouseEvent,
+ base::Unretained(this)));
+ RegisterCommandHandler(
+ devtools::Input::dispatchGestureEvent::kName,
+ base::Bind(
+ &RendererOverridesHandler::InputDispatchGestureEvent,
+ base::Unretained(this)));
}
RendererOverridesHandler::~RendererOverridesHandler() {}
+void RendererOverridesHandler::OnClientDetached() {
+ screencast_command_ = NULL;
+}
+
+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;
+
+ if (screencast_command_)
+ InnerSwapCompositorFrame();
+}
+
+void RendererOverridesHandler::OnVisibilityChanged(bool visible) {
+ if (!screencast_command_)
+ return;
+ NotifyScreencastVisibility(visible);
+}
+
+void RendererOverridesHandler::InnerSwapCompositorFrame() {
+ if ((base::TimeTicks::Now() - last_frame_time_).InMilliseconds() <
+ kFrameRateThresholdMs) {
+ 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());
+
+ gfx::Rect view_bounds = host->GetView()->GetViewBounds();
+ gfx::Size snapshot_size = gfx::ToFlooredSize(
+ gfx::ScaleSize(view_bounds.size(), scale));
+
+ view_port->CopyFromCompositingSurface(
+ view_bounds, snapshot_size,
+ base::Bind(&RendererOverridesHandler::ScreenshotCaptured,
+ weak_factory_.GetWeakPtr(),
+ scoped_refptr<DevToolsProtocol::Command>(), format, quality,
+ last_compositor_frame_metadata_));
+}
+
+void RendererOverridesHandler::ParseCaptureParameters(
+ DevToolsProtocol::Command* command,
+ 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;
+ double max_height = -1;
+ base::DictionaryValue* params = command->params();
+ if (params) {
+ params->GetString(devtools::Page::captureScreenshot::kParamFormat,
+ format);
+ params->GetInteger(devtools::Page::captureScreenshot::kParamQuality,
+ quality);
+ params->GetDouble(devtools::Page::captureScreenshot::kParamMaxWidth,
+ &max_width);
+ params->GetDouble(devtools::Page::captureScreenshot::kParamMaxHeight,
+ &max_height);
+ }
+
+ float device_sf = last_compositor_frame_metadata_.device_scale_factor;
+
+ if (max_width > 0)
+ *scale = std::min(*scale, max_width / view_bounds.width() / device_sf);
+ if (max_height > 0)
+ *scale = std::min(*scale, max_height / view_bounds.height() / device_sf);
+
+ if (format->empty())
+ *format = kPng;
+ if (*quality < 0 || *quality > 100)
+ *quality = kDefaultScreenshotQuality;
+ if (*scale <= 0)
+ *scale = 0.1;
+ if (*scale > 5)
+ *scale = 5;
+}
+
+// DOM agent handlers --------------------------------------------------------
+
scoped_refptr<DevToolsProtocol::Response>
RendererOverridesHandler::GrantPermissionsForSetFileInputFiles(
scoped_refptr<DevToolsProtocol::Command> command) {
@@ -96,6 +255,16 @@ RendererOverridesHandler::GrantPermissionsForSetFileInputFiles(
return NULL;
}
+
+// Page agent handlers -------------------------------------------------------
+
+scoped_refptr<DevToolsProtocol::Response>
+RendererOverridesHandler::PageDisable(
+ scoped_refptr<DevToolsProtocol::Command> command) {
+ screencast_command_ = NULL;
+ return NULL;
+}
+
scoped_refptr<DevToolsProtocol::Response>
RendererOverridesHandler::PageHandleJavaScriptDialog(
scoped_refptr<DevToolsProtocol::Command> command) {
@@ -153,27 +322,94 @@ RendererOverridesHandler::PageNavigate(
}
scoped_refptr<DevToolsProtocol::Response>
+RendererOverridesHandler::PageReload(
+ scoped_refptr<DevToolsProtocol::Command> command) {
+ RenderViewHost* host = agent_->GetRenderViewHost();
+ if (host) {
+ WebContents* web_contents = host->GetDelegate()->GetAsWebContents();
+ if (web_contents) {
+ // Override only if it is crashed.
+ if (!web_contents->IsCrashed())
+ return NULL;
+
+ web_contents->GetController().Reload(false);
+ return command->SuccessResponse(NULL);
+ }
+ }
+ return command->InternalErrorResponse("No WebContents to reload");
+}
+
+scoped_refptr<DevToolsProtocol::Response>
+RendererOverridesHandler::PageGetNavigationHistory(
+ scoped_refptr<DevToolsProtocol::Command> command) {
+ RenderViewHost* host = agent_->GetRenderViewHost();
+ if (host) {
+ WebContents* web_contents = host->GetDelegate()->GetAsWebContents();
+ if (web_contents) {
+ base::DictionaryValue* result = new base::DictionaryValue();
+ NavigationController& controller = web_contents->GetController();
+ result->SetInteger(
+ devtools::Page::getNavigationHistory::kResponseCurrentIndex,
+ controller.GetCurrentEntryIndex());
+ ListValue* entries = new ListValue();
+ for (int i = 0; i != controller.GetEntryCount(); ++i) {
+ const NavigationEntry* entry = controller.GetEntryAtIndex(i);
+ base::DictionaryValue* entry_value = new base::DictionaryValue();
+ entry_value->SetInteger(
+ devtools::Page::getNavigationHistory::kResponseEntryId,
+ entry->GetUniqueID());
+ entry_value->SetString(
+ devtools::Page::getNavigationHistory::kResponseEntryURL,
+ entry->GetURL().spec());
+ entry_value->SetString(
+ devtools::Page::getNavigationHistory::kResponseEntryTitle,
+ entry->GetTitle());
+ entries->Append(entry_value);
+ }
+ result->Set(
+ devtools::Page::getNavigationHistory::kResponseEntries,
+ entries);
+ return command->SuccessResponse(result);
+ }
+ }
+ return command->InternalErrorResponse("No WebContents to navigate");
+}
+
+scoped_refptr<DevToolsProtocol::Response>
+RendererOverridesHandler::PageNavigateToHistoryEntry(
+ scoped_refptr<DevToolsProtocol::Command> command) {
+ int entry_id;
+
+ base::DictionaryValue* params = command->params();
+ const char* param = devtools::Page::navigateToHistoryEntry::kParamEntryId;
+ if (!params || !params->GetInteger(param, &entry_id)) {
+ return command->InvalidParamResponse(param);
+ }
+
+ RenderViewHost* host = agent_->GetRenderViewHost();
+ if (host) {
+ WebContents* web_contents = host->GetDelegate()->GetAsWebContents();
+ if (web_contents) {
+ NavigationController& controller = web_contents->GetController();
+ for (int i = 0; i != controller.GetEntryCount(); ++i) {
+ if (controller.GetEntryAtIndex(i)->GetUniqueID() == entry_id) {
+ controller.GoToIndex(i);
+ return command->SuccessResponse(new base::DictionaryValue());
+ }
+ }
+ return command->InvalidParamResponse(param);
+ }
+ }
+ return command->InternalErrorResponse("No WebContents to navigate");
+}
+
+scoped_refptr<DevToolsProtocol::Response>
RendererOverridesHandler::PageCaptureScreenshot(
scoped_refptr<DevToolsProtocol::Command> command) {
- // Parse input parameters.
std::string format;
int quality = kDefaultScreenshotQuality;
double scale = 1;
- base::DictionaryValue* params = command->params();
- if (params) {
- params->GetString(devtools::Page::captureScreenshot::kParamFormat,
- &format);
- params->GetInteger(devtools::Page::captureScreenshot::kParamQuality,
- &quality);
- params->GetDouble(devtools::Page::captureScreenshot::kParamScale,
- &scale);
- }
- if (format.empty())
- format = kPng;
- if (quality < 0 || quality > 100)
- quality = kDefaultScreenshotQuality;
- if (scale <= 0 || scale > 1)
- scale = 1;
+ ParseCaptureParameters(command.get(), &format, &quality, &scale);
RenderViewHost* host = agent_->GetRenderViewHost();
gfx::Rect view_bounds = host->GetView()->GetViewBounds();
@@ -191,7 +427,7 @@ RendererOverridesHandler::PageCaptureScreenshot(
if (success) {
base::DictionaryValue* result = new base::DictionaryValue();
result->SetString(
- devtools::Page::captureScreenshot::kResponseData, base64_data);
+ devtools::Page::kData, base64_data);
return command->SuccessResponse(result);
}
return command->InternalErrorResponse("Unable to base64encode screenshot");
@@ -206,21 +442,44 @@ RendererOverridesHandler::PageCaptureScreenshot(
view_port->CopyFromCompositingSurface(
view_bounds, snapshot_size,
base::Bind(&RendererOverridesHandler::ScreenshotCaptured,
- weak_factory_.GetWeakPtr(), command, format, quality, scale));
+ weak_factory_.GetWeakPtr(), command, format, quality,
+ last_compositor_frame_metadata_));
return command->AsyncResponsePromise();
}
+scoped_refptr<DevToolsProtocol::Response>
+RendererOverridesHandler::PageStartScreencast(
+ scoped_refptr<DevToolsProtocol::Command> command) {
+ screencast_command_ = command;
+ RenderViewHostImpl* host = static_cast<RenderViewHostImpl*>(
+ agent_->GetRenderViewHost());
+ bool visible = !host->is_hidden();
+ NotifyScreencastVisibility(visible);
+ if (visible)
+ InnerSwapCompositorFrame();
+ return command->SuccessResponse(NULL);
+}
+
+scoped_refptr<DevToolsProtocol::Response>
+RendererOverridesHandler::PageStopScreencast(
+ scoped_refptr<DevToolsProtocol::Command> command) {
+ last_frame_time_ = base::TimeTicks();
+ screencast_command_ = NULL;
+ return command->SuccessResponse(NULL);
+}
+
void RendererOverridesHandler::ScreenshotCaptured(
scoped_refptr<DevToolsProtocol::Command> command,
const std::string& format,
int quality,
- double scale,
+ const cc::CompositorFrameMetadata& metadata,
bool success,
const SkBitmap& bitmap) {
if (!success) {
- SendRawMessage(
- command->InternalErrorResponse("Unable to capture screenshot")->
- Serialize());
+ if (command) {
+ SendAsyncResponse(
+ command->InternalErrorResponse("Unable to capture screenshot"));
+ }
return;
}
@@ -247,27 +506,209 @@ void RendererOverridesHandler::ScreenshotCaptured(
}
if (!encoded) {
- SendRawMessage(
- command->InternalErrorResponse("Unable to encode screenshot")->
- Serialize());
+ if (command) {
+ SendAsyncResponse(
+ command->InternalErrorResponse("Unable to encode screenshot"));
+ }
return;
}
std::string base_64_data;
if (!base::Base64Encode(base::StringPiece(
- reinterpret_cast<char*>(&data[0]),
- data.size()),
+ reinterpret_cast<char*>(&data[0]),
+ data.size()),
&base_64_data)) {
- SendRawMessage(
- command->InternalErrorResponse("Unable to base64 encode screenshot")->
- Serialize());
+ if (command) {
+ SendAsyncResponse(
+ command->InternalErrorResponse("Unable to base64 encode"));
+ }
return;
}
base::DictionaryValue* response = new base::DictionaryValue();
- response->SetString(
- devtools::Page::captureScreenshot::kResponseData, base_64_data);
- SendRawMessage(command->SuccessResponse(response)->Serialize());
+ response->SetString(devtools::Page::kData, 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* 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,
+ metadata.viewport_size.height());
+ response->Set(devtools::Page::kParamViewport, viewport);
+ }
+
+ if (command) {
+ SendAsyncResponse(command->SuccessResponse(response));
+ } else {
+ SendNotification(devtools::Page::screencastFrame::kName, response);
+ }
+}
+
+void RendererOverridesHandler::NotifyScreencastVisibility(bool visible) {
+ base::DictionaryValue* params = new base::DictionaryValue();
+ params->SetBoolean(
+ devtools::Page::screencastVisibilityChanged::kParamVisible, visible);
+ SendNotification(
+ devtools::Page::screencastVisibilityChanged::kName, params);
+}
+
+// Input agent handlers ------------------------------------------------------
+
+scoped_refptr<DevToolsProtocol::Response>
+RendererOverridesHandler::InputDispatchMouseEvent(
+ scoped_refptr<DevToolsProtocol::Command> command) {
+ base::DictionaryValue* params = command->params();
+ if (!params)
+ return NULL;
+
+ bool device_space = false;
+ if (!params->GetBoolean(devtools::Input::kParamDeviceSpace,
+ &device_space) ||
+ !device_space) {
+ return NULL;
+ }
+
+ RenderViewHost* host = agent_->GetRenderViewHost();
+ WebKit::WebMouseEvent mouse_event;
+ ParseGenericInputParams(params, &mouse_event);
+
+ std::string type;
+ if (params->GetString(devtools::Input::kParamType,
+ &type)) {
+ if (type == "mousePressed")
+ mouse_event.type = WebInputEvent::MouseDown;
+ else if (type == "mouseReleased")
+ mouse_event.type = WebInputEvent::MouseUp;
+ else if (type == "mouseMoved")
+ mouse_event.type = WebInputEvent::MouseMove;
+ else
+ return NULL;
+ } else {
+ return NULL;
+ }
+
+ if (!params->GetInteger(devtools::kParamX, &mouse_event.x) ||
+ !params->GetInteger(devtools::kParamY, &mouse_event.y)) {
+ return NULL;
+ }
+
+ mouse_event.windowX = mouse_event.x;
+ mouse_event.windowY = mouse_event.y;
+ mouse_event.globalX = mouse_event.x;
+ mouse_event.globalY = mouse_event.y;
+
+ params->GetInteger(devtools::Input::dispatchMouseEvent::kParamClickCount,
+ &mouse_event.clickCount);
+
+ std::string button;
+ if (!params->GetString(devtools::Input::dispatchMouseEvent::kParamButton,
+ &button)) {
+ return NULL;
+ }
+
+ if (button == "none") {
+ mouse_event.button = WebMouseEvent::ButtonNone;
+ } else if (button == "left") {
+ mouse_event.button = WebMouseEvent::ButtonLeft;
+ mouse_event.modifiers |= WebInputEvent::LeftButtonDown;
+ } else if (button == "middle") {
+ mouse_event.button = WebMouseEvent::ButtonMiddle;
+ mouse_event.modifiers |= WebInputEvent::MiddleButtonDown;
+ } else if (button == "right") {
+ mouse_event.button = WebMouseEvent::ButtonRight;
+ mouse_event.modifiers |= WebInputEvent::RightButtonDown;
+ } else {
+ return NULL;
+ }
+
+ host->ForwardMouseEvent(mouse_event);
+ return command->SuccessResponse(NULL);
+}
+
+scoped_refptr<DevToolsProtocol::Response>
+RendererOverridesHandler::InputDispatchGestureEvent(
+ scoped_refptr<DevToolsProtocol::Command> command) {
+ base::DictionaryValue* params = command->params();
+ if (!params)
+ return NULL;
+
+ RenderViewHostImpl* host = static_cast<RenderViewHostImpl*>(
+ agent_->GetRenderViewHost());
+ WebKit::WebGestureEvent event;
+ ParseGenericInputParams(params, &event);
+
+ std::string type;
+ if (params->GetString(devtools::Input::kParamType,
+ &type)) {
+ if (type == "scrollBegin")
+ event.type = WebInputEvent::GestureScrollBegin;
+ else if (type == "scrollUpdate")
+ event.type = WebInputEvent::GestureScrollUpdate;
+ else if (type == "scrollEnd")
+ event.type = WebInputEvent::GestureScrollEnd;
+ else if (type == "tapDown")
+ event.type = WebInputEvent::GestureTapDown;
+ else if (type == "tap")
+ event.type = WebInputEvent::GestureTap;
+ else if (type == "pinchBegin")
+ event.type = WebInputEvent::GesturePinchBegin;
+ else if (type == "pinchUpdate")
+ event.type = WebInputEvent::GesturePinchUpdate;
+ else if (type == "pinchEnd")
+ event.type = WebInputEvent::GesturePinchEnd;
+ else
+ return NULL;
+ } else {
+ return NULL;
+ }
+
+ if (!params->GetInteger(devtools::kParamX, &event.x) ||
+ !params->GetInteger(devtools::kParamY, &event.y)) {
+ return NULL;
+ }
+ event.globalX = event.x;
+ event.globalY = event.y;
+
+ if (type == "scrollUpdate") {
+ int dx;
+ int dy;
+ if (!params->GetInteger(
+ devtools::Input::dispatchGestureEvent::kParamDeltaX, &dx) ||
+ !params->GetInteger(
+ devtools::Input::dispatchGestureEvent::kParamDeltaY, &dy)) {
+ return NULL;
+ }
+ event.data.scrollUpdate.deltaX = dx;
+ event.data.scrollUpdate.deltaY = dy;
+ }
+
+ if (type == "pinchUpdate") {
+ double scale;
+ if (!params->GetDouble(
+ devtools::Input::dispatchGestureEvent::kParamPinchScale,
+ &scale)) {
+ return NULL;
+ }
+ event.data.pinchUpdate.scale = static_cast<float>(scale);
+ }
+
+ host->ForwardGestureEvent(event);
+ return command->SuccessResponse(NULL);
}
} // namespace content
diff --git a/chromium/content/browser/devtools/renderer_overrides_handler.h b/chromium/content/browser/devtools/renderer_overrides_handler.h
index 1d4213d8be6..a5336bf4542 100644
--- a/chromium/content/browser/devtools/renderer_overrides_handler.h
+++ b/chromium/content/browser/devtools/renderer_overrides_handler.h
@@ -9,10 +9,16 @@
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+#include "cc/output/compositor_frame_metadata.h"
#include "content/browser/devtools/devtools_protocol.h"
class SkBitmap;
+namespace IPC {
+class Message;
+}
+
namespace content {
class DevToolsAgentHost;
@@ -26,27 +32,62 @@ class RendererOverridesHandler : public DevToolsProtocol::Handler {
explicit RendererOverridesHandler(DevToolsAgentHost* agent);
virtual ~RendererOverridesHandler();
+ void OnClientDetached();
+ void OnSwapCompositorFrame(const IPC::Message& message);
+ void OnVisibilityChanged(bool visible);
+
private:
+ void InnerSwapCompositorFrame();
+ void ParseCaptureParameters(DevToolsProtocol::Command* command,
+ std::string* format, int* quality,
+ double* scale);
+
+ // DOM domain.
scoped_refptr<DevToolsProtocol::Response>
GrantPermissionsForSetFileInputFiles(
scoped_refptr<DevToolsProtocol::Command> command);
+
+ // Page domain.
+ scoped_refptr<DevToolsProtocol::Response> PageDisable(
+ scoped_refptr<DevToolsProtocol::Command> command);
scoped_refptr<DevToolsProtocol::Response> PageHandleJavaScriptDialog(
scoped_refptr<DevToolsProtocol::Command> command);
scoped_refptr<DevToolsProtocol::Response> PageNavigate(
scoped_refptr<DevToolsProtocol::Command> command);
+ scoped_refptr<DevToolsProtocol::Response> PageReload(
+ scoped_refptr<DevToolsProtocol::Command> command);
+ scoped_refptr<DevToolsProtocol::Response> PageGetNavigationHistory(
+ scoped_refptr<DevToolsProtocol::Command> command);
+ scoped_refptr<DevToolsProtocol::Response> PageNavigateToHistoryEntry(
+ scoped_refptr<DevToolsProtocol::Command> command);
scoped_refptr<DevToolsProtocol::Response> PageCaptureScreenshot(
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);
void ScreenshotCaptured(
scoped_refptr<DevToolsProtocol::Command> command,
const std::string& format,
int quality,
- double scale,
+ const cc::CompositorFrameMetadata& metadata,
bool success,
const SkBitmap& bitmap);
+ void NotifyScreencastVisibility(bool visible);
+
+ // Input domain.
+ scoped_refptr<DevToolsProtocol::Response> InputDispatchMouseEvent(
+ scoped_refptr<DevToolsProtocol::Command> command);
+ scoped_refptr<DevToolsProtocol::Response> InputDispatchGestureEvent(
+ 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_;
DISALLOW_COPY_AND_ASSIGN(RendererOverridesHandler);
};
diff --git a/chromium/content/browser/devtools/tethering_handler.cc b/chromium/content/browser/devtools/tethering_handler.cc
index 711adcd2d72..d3e787d0c01 100644
--- a/chromium/content/browser/devtools/tethering_handler.cc
+++ b/chromium/content/browser/devtools/tethering_handler.cc
@@ -61,7 +61,7 @@ class SocketPump : public net::StreamListenSocket::Delegate {
private:
virtual void DidAccept(net::StreamListenSocket* server,
- net::StreamListenSocket* socket) OVERRIDE {
+ scoped_ptr<net::StreamListenSocket> socket) OVERRIDE {
if (accepted_socket_.get())
return;
@@ -69,7 +69,7 @@ class SocketPump : public net::StreamListenSocket::Delegate {
wire_buffer_ = new net::GrowableIOBuffer();
wire_buffer_->SetCapacity(kBufferSize);
- accepted_socket_ = socket;
+ accepted_socket_ = socket.Pass();
int result = client_socket_->Read(
buffer_.get(),
kBufferSize,
@@ -158,8 +158,8 @@ class SocketPump : public net::StreamListenSocket::Delegate {
private:
scoped_ptr<net::StreamSocket> client_socket_;
- scoped_refptr<net::StreamListenSocket> server_socket_;
- scoped_refptr<net::StreamListenSocket> accepted_socket_;
+ scoped_ptr<net::StreamListenSocket> server_socket_;
+ scoped_ptr<net::StreamListenSocket> accepted_socket_;
scoped_refptr<net::IOBuffer> buffer_;
scoped_refptr<net::GrowableIOBuffer> wire_buffer_;
DevToolsHttpHandlerDelegate* delegate_;
diff --git a/chromium/content/browser/devtools/worker_devtools_manager.cc b/chromium/content/browser/devtools/worker_devtools_manager.cc
index 14efaa53d41..983c55cfb2b 100644
--- a/chromium/content/browser/devtools/worker_devtools_manager.cc
+++ b/chromium/content/browser/devtools/worker_devtools_manager.cc
@@ -32,6 +32,16 @@ scoped_refptr<DevToolsAgentHost> DevToolsAgentHost::GetForWorker(
worker_route_id);
}
+// Called on the UI thread.
+// static
+bool DevToolsAgentHost::HasForWorker(
+ int worker_process_id,
+ int worker_route_id) {
+ return WorkerDevToolsManager::HasDevToolsAgentHostForWorker(
+ worker_process_id,
+ worker_route_id);
+}
+
namespace {
typedef std::map<WorkerDevToolsManager::WorkerId,
@@ -196,6 +206,14 @@ DevToolsAgentHost* WorkerDevToolsManager::GetDevToolsAgentHostForWorker(
return it->second;
}
+// static
+bool WorkerDevToolsManager::HasDevToolsAgentHostForWorker(
+ int worker_process_id,
+ int worker_route_id) {
+ WorkerId id(worker_process_id, worker_route_id);
+ return g_agent_map.Get().find(id) != g_agent_map.Get().end();
+}
+
WorkerDevToolsManager::WorkerDevToolsManager() {
}
diff --git a/chromium/content/browser/devtools/worker_devtools_manager.h b/chromium/content/browser/devtools/worker_devtools_manager.h
index 0f0111ecf30..e6d090c2159 100644
--- a/chromium/content/browser/devtools/worker_devtools_manager.h
+++ b/chromium/content/browser/devtools/worker_devtools_manager.h
@@ -32,6 +32,11 @@ class WorkerDevToolsManager {
int worker_process_id,
int worker_route_id);
+ // Called on the UI thread.
+ static bool HasDevToolsAgentHostForWorker(
+ int worker_process_id,
+ int worker_route_id);
+
void ForwardToDevToolsClient(int worker_process_id,
int worker_route_id,
const std::string& message);
diff --git a/chromium/content/browser/dom_storage/dom_storage_browsertest.cc b/chromium/content/browser/dom_storage/dom_storage_browsertest.cc
index 54da50a7272..b2aa9f1592b 100644
--- a/chromium/content/browser/dom_storage/dom_storage_browsertest.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_browsertest.cc
@@ -7,7 +7,7 @@
#include "content/common/dom_storage/dom_storage_types.h"
#include "content/public/common/content_paths.h"
#include "content/public/test/browser_test_utils.h"
-#include "content/shell/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
#include "net/base/net_util.h"
@@ -25,7 +25,8 @@ class DOMStorageBrowserTest : public ContentBrowserTest {
// a #pass or #fail ref.
Shell* the_browser = incognito ? CreateOffTheRecordBrowser() : shell();
NavigateToURLBlockUntilNavigationsComplete(the_browser, test_url, 2);
- std::string result = the_browser->web_contents()->GetURL().ref();
+ std::string result =
+ the_browser->web_contents()->GetLastCommittedURL().ref();
if (result != "pass") {
std::string js_result;
ASSERT_TRUE(ExecuteScriptAndExtractString(
diff --git a/chromium/content/browser/dom_storage/dom_storage_host.cc b/chromium/content/browser/dom_storage/dom_storage_host.cc
index 296d52ec6d7..14d288d8653 100644
--- a/chromium/content/browser/dom_storage/dom_storage_host.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_host.cc
@@ -30,12 +30,8 @@ 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()) {
- // 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 (!references.namespace_.get())
+ return false;
references.area_ = references.namespace_->OpenStorageArea(origin);
DCHECK(references.area_.get());
connections_[connection_id] = references;
@@ -54,12 +50,8 @@ bool DOMStorageHost::ExtractAreaValues(
int connection_id, DOMStorageValuesMap* map) {
map->clear();
DOMStorageArea* area = GetOpenArea(connection_id);
- 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)
+ return false;
if (!area->IsLoadedInMemory()) {
DOMStorageNamespace* ns = GetNamespace(connection_id);
DCHECK(ns);
@@ -101,12 +93,8 @@ bool DOMStorageHost::SetAreaItem(
const base::string16& value, const GURL& page_url,
base::NullableString16* old_value) {
DOMStorageArea* area = GetOpenArea(connection_id);
- 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)
+ return false;
if (!area->SetItem(key, value, old_value))
return false;
if (old_value->is_null() || old_value->string() != value)
diff --git a/chromium/content/browser/dom_storage/session_storage_database.cc b/chromium/content/browser/dom_storage/session_storage_database.cc
index 5fb0c90da3b..bac3df7a67b 100644
--- a/chromium/content/browser/dom_storage/session_storage_database.cc
+++ b/chromium/content/browser/dom_storage/session_storage_database.cc
@@ -326,7 +326,7 @@ leveldb::Status SessionStorageDatabase::TryToOpen(leveldb::DB** db) {
// The directory exists but a valid leveldb database might not exist inside it
// (e.g., a subset of the needed files might be missing). Handle this
// situation gracefully by creating the database now.
- options.max_open_files = 64; // Use minimum.
+ options.max_open_files = 0; // Use minimum.
options.create_if_missing = true;
#if defined(OS_WIN)
return leveldb::DB::Open(options, WideToUTF8(file_path_.value()), db);
diff --git a/chromium/content/browser/dom_storage/session_storage_database_unittest.cc b/chromium/content/browser/dom_storage/session_storage_database_unittest.cc
index 9722d72925c..2f86c3b9918 100644
--- a/chromium/content/browser/dom_storage/session_storage_database_unittest.cc
+++ b/chromium/content/browser/dom_storage/session_storage_database_unittest.cc
@@ -219,7 +219,6 @@ void SessionStorageDatabaseTest::CheckDatabaseConsistency() const {
for (DataMap::const_iterator it = data.begin(); it != data.end(); ++it) {
std::string namespace_id;
- std::string origin;
if (IsNamespaceKey(it->first, &namespace_id)) {
found_namespace_ids.insert(namespace_id);
++valid_keys;
diff --git a/chromium/content/browser/download/base_file_unittest.cc b/chromium/content/browser/download/base_file_unittest.cc
index 826f56b4cf8..b82b0a8ab70 100644
--- a/chromium/content/browser/download/base_file_unittest.cc
+++ b/chromium/content/browser/download/base_file_unittest.cc
@@ -71,7 +71,7 @@ class BaseFileTest : public testing::Test {
if (!expected_data_.empty() && !expected_error_) {
// Make sure the data has been properly written to disk.
std::string disk_data;
- EXPECT_TRUE(file_util::ReadFileToString(full_path, &disk_data));
+ EXPECT_TRUE(base::ReadFileToString(full_path, &disk_data));
EXPECT_EQ(expected_data_, disk_data);
}
diff --git a/chromium/content/browser/download/download_browsertest.cc b/chromium/content/browser/download/download_browsertest.cc
index 79ad19c9839..767819edbcf 100644
--- a/chromium/content/browser/download/download_browsertest.cc
+++ b/chromium/content/browser/download/download_browsertest.cc
@@ -22,12 +22,14 @@
#include "content/public/browser/power_save_blocker.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/webplugininfo.h"
+#include "content/public/test/browser_test_utils.h"
#include "content/public/test/download_test_observer.h"
#include "content/public/test/test_file_error_injector.h"
#include "content/public/test/test_utils.h"
-#include "content/shell/shell.h"
-#include "content/shell/shell_browser_context.h"
-#include "content/shell/shell_download_manager_delegate.h"
+#include "content/shell/browser/shell.h"
+#include "content/shell/browser/shell_browser_context.h"
+#include "content/shell/browser/shell_download_manager_delegate.h"
+#include "content/shell/browser/shell_network_delegate.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"
@@ -598,7 +600,7 @@ class DownloadContentTest : public ContentBrowserTest {
const int64 file_size) {
std::string file_contents;
- bool read = file_util::ReadFileToString(path, &file_contents);
+ bool read = base::ReadFileToString(path, &file_contents);
EXPECT_TRUE(read) << "Failed reading file: " << path.value() << std::endl;
if (!read)
return false; // Couldn't read the file.
@@ -672,7 +674,7 @@ class DownloadContentTest : public ContentBrowserTest {
if (file_exists) {
std::string file_contents;
- EXPECT_TRUE(file_util::ReadFileToString(
+ EXPECT_TRUE(base::ReadFileToString(
download->GetFullPath(), &file_contents));
ASSERT_EQ(static_cast<size_t>(received_bytes), file_contents.size());
@@ -1598,4 +1600,42 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelResumingDownload) {
EXPECT_TRUE(EnsureNoPendingDownloads());
}
+// Check that the cookie policy is correctly updated when downloading a file
+// that redirects cross origin.
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, CookiePolicy) {
+ ASSERT_TRUE(test_server()->Start());
+ net::HostPortPair host_port = test_server()->host_port_pair();
+ DCHECK_EQ(host_port.host(), std::string("127.0.0.1"));
+
+ // Block third-party cookies.
+ ShellNetworkDelegate::SetAcceptAllCookies(false);
+
+ // |url| redirects to a different origin |download| which tries to set a
+ // cookie.
+ std::string download(base::StringPrintf(
+ "http://localhost:%d/set-cookie?A=B", host_port.port()));
+ GURL url(test_server()->GetURL("server-redirect?" + download));
+
+ // Download the file.
+ SetupEnsureNoPendingDownloads();
+ scoped_ptr<DownloadUrlParameters> dl_params(
+ DownloadUrlParameters::FromWebContents(shell()->web_contents(), url));
+ scoped_ptr<DownloadTestObserver> observer(CreateWaiter(shell(), 1));
+ DownloadManagerForShell(shell())->DownloadUrl(dl_params.Pass());
+ observer->WaitForFinished();
+
+ // Get the important info from other threads and check it.
+ EXPECT_TRUE(EnsureNoPendingDownloads());
+
+ std::vector<DownloadItem*> downloads;
+ DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
+ ASSERT_EQ(1u, downloads.size());
+ ASSERT_EQ(DownloadItem::COMPLETE, downloads[0]->GetState());
+
+ // Check that the cookies were correctly set.
+ EXPECT_EQ("A=B",
+ content::GetCookies(shell()->web_contents()->GetBrowserContext(),
+ GURL(download)));
+}
+
} // namespace content
diff --git a/chromium/content/browser/download/download_file_unittest.cc b/chromium/content/browser/download/download_file_unittest.cc
index 867b76f6fef..dcc0e424bd2 100644
--- a/chromium/content/browser/download/download_file_unittest.cc
+++ b/chromium/content/browser/download/download_file_unittest.cc
@@ -76,6 +76,7 @@ class DownloadFileTest : public testing::Test {
DownloadFileTest() :
observer_(new StrictMock<MockDownloadDestinationObserver>),
observer_factory_(observer_.get()),
+ input_stream_(NULL),
bytes_(-1),
bytes_per_sec_(-1),
hash_state_("xyzzy"),
@@ -163,8 +164,7 @@ class DownloadFileTest : public testing::Test {
// Make sure the data has been properly written to disk.
std::string disk_data;
- EXPECT_TRUE(file_util::ReadFileToString(download_file_->FullPath(),
- &disk_data));
+ EXPECT_TRUE(base::ReadFileToString(download_file_->FullPath(), &disk_data));
EXPECT_EQ(expected_data_, disk_data);
// Make sure the Browser and File threads outlive the DownloadFile
@@ -416,7 +416,7 @@ TEST_F(DownloadFileTest, RenameFileFinal) {
ASSERT_EQ(static_cast<int>(sizeof(file_data) - 1),
file_util::WriteFile(path_5, file_data, sizeof(file_data) - 1));
ASSERT_TRUE(base::PathExists(path_5));
- EXPECT_TRUE(file_util::ReadFileToString(path_5, &file_contents));
+ EXPECT_TRUE(base::ReadFileToString(path_5, &file_contents));
EXPECT_EQ(std::string(file_data), file_contents);
EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
@@ -424,7 +424,7 @@ TEST_F(DownloadFileTest, RenameFileFinal) {
EXPECT_EQ(path_5, output_path);
file_contents = "";
- EXPECT_TRUE(file_util::ReadFileToString(path_5, &file_contents));
+ EXPECT_TRUE(base::ReadFileToString(path_5, &file_contents));
EXPECT_NE(std::string(file_data), file_contents);
DestroyDownloadFile(0);
diff --git a/chromium/content/browser/download/download_manager_impl_unittest.cc b/chromium/content/browser/download/download_manager_impl_unittest.cc
index eba28339b51..0865c04b2fa 100644
--- a/chromium/content/browser/download/download_manager_impl_unittest.cc
+++ b/chromium/content/browser/download/download_manager_impl_unittest.cc
@@ -435,7 +435,8 @@ class DownloadManagerTest : public testing::Test {
static const size_t kTestDataLen;
DownloadManagerTest()
- : ui_thread_(BrowserThread::UI, &message_loop_),
+ : callback_called_(false),
+ ui_thread_(BrowserThread::UI, &message_loop_),
file_thread_(BrowserThread::FILE, &message_loop_),
next_download_id_(0) {
}
diff --git a/chromium/content/browser/download/download_resource_handler.cc b/chromium/content/browser/download/download_resource_handler.cc
index 3b4844e6e68..ed4edff67fe 100644
--- a/chromium/content/browser/download/download_resource_handler.cc
+++ b/chromium/content/browser/download/download_resource_handler.cc
@@ -103,6 +103,9 @@ bool DownloadResourceHandler::OnRequestRedirected(
const GURL& url,
ResourceResponse* response,
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);
return true;
}
diff --git a/chromium/content/browser/download/download_resource_handler.h b/chromium/content/browser/download/download_resource_handler.h
index d38068d5482..60fbc944387 100644
--- a/chromium/content/browser/download/download_resource_handler.h
+++ b/chromium/content/browser/download/download_resource_handler.h
@@ -49,7 +49,6 @@ class CONTENT_EXPORT DownloadResourceHandler
uint64 position,
uint64 size) OVERRIDE;
- // Not needed, as this event handler ought to be the final resource.
virtual bool OnRequestRedirected(int request_id,
const GURL& url,
ResourceResponse* response,
diff --git a/chromium/content/browser/download/drag_download_file_browsertest.cc b/chromium/content/browser/download/drag_download_file_browsertest.cc
index fc35d6c04e0..a4f50056ad3 100644
--- a/chromium/content/browser/download/drag_download_file_browsertest.cc
+++ b/chromium/content/browser/download/drag_download_file_browsertest.cc
@@ -16,9 +16,9 @@
#include "content/public/common/content_client.h"
#include "content/public/test/download_test_observer.h"
#include "content/public/test/test_utils.h"
-#include "content/shell/shell.h"
-#include "content/shell/shell_browser_context.h"
-#include "content/shell/shell_download_manager_delegate.h"
+#include "content/shell/browser/shell.h"
+#include "content/shell/browser/shell_browser_context.h"
+#include "content/shell/browser/shell_download_manager_delegate.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
#include "content/test/net/url_request_mock_http_job.h"
diff --git a/chromium/content/browser/download/file_metadata_mac.mm b/chromium/content/browser/download/file_metadata_mac.mm
index fc0556e0a3b..9dc504fcc49 100644
--- a/chromium/content/browser/download/file_metadata_mac.mm
+++ b/chromium/content/browser/download/file_metadata_mac.mm
@@ -132,7 +132,7 @@ void AddQuarantineMetadataToFile(const base::FilePath& file, const GURL& source,
// need to set the values that the OS can't infer.
if (![quarantine_properties valueForKey:(NSString*)kLSQuarantineTypeKey]) {
- CFStringRef type = (source.SchemeIs("http") || source.SchemeIs("https"))
+ CFStringRef type = source.SchemeIsHTTPOrHTTPS()
? kLSQuarantineTypeWebDownload
: kLSQuarantineTypeOtherDownload;
[quarantine_properties setValue:(NSString*)type
diff --git a/chromium/content/browser/download/file_metadata_unittest_linux.cc b/chromium/content/browser/download/file_metadata_unittest_linux.cc
index bc8666e076c..4a3ebca5a2c 100644
--- a/chromium/content/browser/download/file_metadata_unittest_linux.cc
+++ b/chromium/content/browser/download/file_metadata_unittest_linux.cc
@@ -30,7 +30,8 @@ class FileMetadataLinuxTest : public testing::Test {
public:
FileMetadataLinuxTest()
: source_url_("http://www.source.com"),
- referrer_url_("http://www.referrer.com") {}
+ referrer_url_("http://www.referrer.com"),
+ is_xattr_supported_(false) {}
const base::FilePath& test_file() const {
return test_file_;
diff --git a/chromium/content/browser/download/mhtml_generation_browsertest.cc b/chromium/content/browser/download/mhtml_generation_browsertest.cc
index 07bffed6b4b..6e790135bce 100644
--- a/chromium/content/browser/download/mhtml_generation_browsertest.cc
+++ b/chromium/content/browser/download/mhtml_generation_browsertest.cc
@@ -9,7 +9,7 @@
#include "base/run_loop.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/test_utils.h"
-#include "content/shell/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
@@ -21,7 +21,7 @@ class MHTMLGenerationTest : public ContentBrowserTest {
public:
MHTMLGenerationTest() : mhtml_generated_(false), file_size_(0) {}
- void MHTMLGenerated(const base::FilePath& path, int64 size) {
+ void MHTMLGenerated(int64 size) {
mhtml_generated_ = true;
file_size_ = size;
base::MessageLoopForUI::current()->Quit();
diff --git a/chromium/content/browser/download/mhtml_generation_manager.cc b/chromium/content/browser/download/mhtml_generation_manager.cc
index c4bc378c148..7d7d4bb2645 100644
--- a/chromium/content/browser/download/mhtml_generation_manager.cc
+++ b/chromium/content/browser/download/mhtml_generation_manager.cc
@@ -36,29 +36,12 @@ MHTMLGenerationManager::MHTMLGenerationManager() {
MHTMLGenerationManager::~MHTMLGenerationManager() {
}
-void MHTMLGenerationManager::GenerateMHTML(
- WebContents* web_contents,
- const base::FilePath& file,
- const GenerateMHTMLCallback& callback) {
+void MHTMLGenerationManager::SaveMHTML(WebContents* web_contents,
+ const base::FilePath& file,
+ const GenerateMHTMLCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- static int id_counter = 0;
- int job_id = id_counter++;
- Job job;
- job.file_path = file;
- job.process_id = web_contents->GetRenderProcessHost()->GetID();
- job.routing_id = web_contents->GetRenderViewHost()->GetRoutingID();
- job.callback = callback;
- id_to_job_[job_id] = job;
- if (!registrar_.IsRegistered(
- this,
- NOTIFICATION_RENDERER_PROCESS_TERMINATED,
- Source<RenderProcessHost>(web_contents->GetRenderProcessHost()))) {
- registrar_.Add(
- this,
- NOTIFICATION_RENDERER_PROCESS_TERMINATED,
- Source<RenderProcessHost>(web_contents->GetRenderProcessHost()));
- }
+ int job_id = NewJob(web_contents, callback);
base::ProcessHandle renderer_process =
web_contents->GetRenderProcessHost()->GetHandle();
@@ -67,6 +50,23 @@ void MHTMLGenerationManager::GenerateMHTML(
job_id, file, renderer_process));
}
+void MHTMLGenerationManager::StreamMHTML(
+ WebContents* web_contents,
+ const base::PlatformFile browser_file,
+ const GenerateMHTMLCallback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ int job_id = NewJob(web_contents, callback);
+
+ base::ProcessHandle renderer_process =
+ web_contents->GetRenderProcessHost()->GetHandle();
+ IPC::PlatformFileForTransit renderer_file =
+ IPC::GetFileHandleForProcess(browser_file, renderer_process, false);
+
+ FileHandleAvailable(job_id, browser_file, renderer_file);
+}
+
+
void MHTMLGenerationManager::MHTMLGenerated(int job_id, int64 mhtml_data_size) {
JobFinished(job_id, mhtml_data_size);
}
@@ -86,12 +86,17 @@ void MHTMLGenerationManager::CreateFile(
IPC::PlatformFileForTransit renderer_file =
IPC::GetFileHandleForProcess(browser_file, renderer_process, false);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&MHTMLGenerationManager::FileCreated, base::Unretained(this),
- job_id, browser_file, renderer_file));
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&MHTMLGenerationManager::FileHandleAvailable,
+ base::Unretained(this),
+ job_id,
+ browser_file,
+ renderer_file));
}
-void MHTMLGenerationManager::FileCreated(int job_id,
+void MHTMLGenerationManager::FileHandleAvailable(int job_id,
base::PlatformFile browser_file,
IPC::PlatformFileForTransit renderer_file) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -131,7 +136,7 @@ void MHTMLGenerationManager::JobFinished(int job_id, int64 file_size) {
}
Job& job = iter->second;
- job.callback.Run(job.file_path, file_size);
+ job.callback.Run(file_size);
BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
base::Bind(&MHTMLGenerationManager::CloseFile, base::Unretained(this),
@@ -145,6 +150,26 @@ void MHTMLGenerationManager::CloseFile(base::PlatformFile file) {
base::ClosePlatformFile(file);
}
+int MHTMLGenerationManager::NewJob(WebContents* web_contents,
+ const GenerateMHTMLCallback& callback) {
+ static int id_counter = 0;
+ int job_id = id_counter++;
+ Job& job = id_to_job_[job_id];
+ job.process_id = web_contents->GetRenderProcessHost()->GetID();
+ job.routing_id = web_contents->GetRenderViewHost()->GetRoutingID();
+ job.callback = callback;
+ if (!registrar_.IsRegistered(
+ this,
+ NOTIFICATION_RENDERER_PROCESS_TERMINATED,
+ Source<RenderProcessHost>(web_contents->GetRenderProcessHost()))) {
+ registrar_.Add(
+ this,
+ NOTIFICATION_RENDERER_PROCESS_TERMINATED,
+ Source<RenderProcessHost>(web_contents->GetRenderProcessHost()));
+ }
+ return job_id;
+}
+
void MHTMLGenerationManager::Observe(int type,
const NotificationSource& source,
const NotificationDetails& details) {
diff --git a/chromium/content/browser/download/mhtml_generation_manager.h b/chromium/content/browser/download/mhtml_generation_manager.h
index 0c9ec619557..5525d99b812 100644
--- a/chromium/content/browser/download/mhtml_generation_manager.h
+++ b/chromium/content/browser/download/mhtml_generation_manager.h
@@ -25,14 +25,20 @@ class MHTMLGenerationManager : public NotificationObserver {
public:
static MHTMLGenerationManager* GetInstance();
- typedef base::Callback<void(const base::FilePath& /* path to the MHTML file */,
- int64 /* size of the file */)> GenerateMHTMLCallback;
+ typedef base::Callback<void(int64 /* size of the file */)>
+ GenerateMHTMLCallback;
// Instructs the render view to generate a MHTML representation of the current
// page for |web_contents|.
- void GenerateMHTML(WebContents* web_contents,
- const base::FilePath& file,
- const GenerateMHTMLCallback& callback);
+ void SaveMHTML(WebContents* web_contents,
+ const base::FilePath& file,
+ const GenerateMHTMLCallback& callback);
+
+ // Instructs the render view to generate a MHTML representation of the current
+ // page for |web_contents|.
+ void StreamMHTML(WebContents* web_contents,
+ const base::PlatformFile file,
+ const GenerateMHTMLCallback& callback);
// Notification from the renderer that the MHTML generation finished.
// |mhtml_data_size| contains the size in bytes of the generated MHTML data,
@@ -46,8 +52,6 @@ class MHTMLGenerationManager : public NotificationObserver {
Job();
~Job();
- base::FilePath file_path;
-
// The handles to file the MHTML is saved to, for the browser and renderer
// processes.
base::PlatformFile browser_file;
@@ -73,9 +77,9 @@ class MHTMLGenerationManager : public NotificationObserver {
// been created. This returns a handle to that file for the browser process
// and one for the renderer process. These handles are
// kInvalidPlatformFileValue if the file could not be opened.
- void FileCreated(int job_id,
- base::PlatformFile browser_file,
- IPC::PlatformFileForTransit renderer_file);
+ void FileHandleAvailable(int job_id,
+ base::PlatformFile browser_file,
+ IPC::PlatformFileForTransit renderer_file);
// Called on the file thread to close the file the MHTML was saved to.
void CloseFile(base::PlatformFile file);
@@ -85,6 +89,9 @@ class MHTMLGenerationManager : public NotificationObserver {
// |mhtml_data_size| is -1 if the MHTML generation failed.
void JobFinished(int job_id, int64 mhtml_data_size);
+ // Creates an register a new job.
+ int NewJob(WebContents* web_contents, const GenerateMHTMLCallback& callback);
+
// Implementation of NotificationObserver.
virtual void Observe(int type,
const NotificationSource& source,
diff --git a/chromium/content/browser/download/save_package.cc b/chromium/content/browser/download/save_package.cc
index a386a2be0c3..f38f9cdb1e4 100644
--- a/chromium/content/browser/download/save_package.cc
+++ b/chromium/content/browser/download/save_package.cc
@@ -363,7 +363,7 @@ void SavePackage::InitWithDownloadItem(
}
}
-void SavePackage::OnMHTMLGenerated(const base::FilePath& path, int64 size) {
+void SavePackage::OnMHTMLGenerated(int64 size) {
if (size <= 0) {
Cancel(false);
return;
@@ -971,11 +971,11 @@ void SavePackage::DoSavingProcess() {
// sub-resource's link can be replaced with local file path, which
// sub-resource's link need to be replaced with absolute URL which
// point to its internet address because it got error when saving its data.
- SaveItem* save_item = NULL;
+
// Start a new SaveItem job if we still have job in waiting queue.
if (waiting_item_queue_.size()) {
DCHECK(wait_state_ == NET_FILES);
- save_item = waiting_item_queue_.front();
+ SaveItem* save_item = waiting_item_queue_.front();
if (save_item->save_source() != SaveFileCreateInfo::SAVE_FILE_FROM_DOM) {
SaveNextFile(false);
} else if (!in_process_count()) {
@@ -1209,8 +1209,7 @@ base::FilePath SavePackage::GetSuggestedNameForSaveAs(
bool can_save_as_complete,
const std::string& contents_mime_type,
const std::string& accept_langs) {
- base::FilePath name_with_proper_ext =
- base::FilePath::FromWStringHack(UTF16ToWideHack(title_));
+ base::FilePath name_with_proper_ext = base::FilePath::FromUTF16Unsafe(title_);
// If the page's title matches its URL, use the URL. Try to use the last path
// component or if there is none, the domain as the file name.
@@ -1238,8 +1237,7 @@ base::FilePath SavePackage::GetSuggestedNameForSaveAs(
} else {
url_path = "dataurl";
}
- name_with_proper_ext =
- base::FilePath::FromWStringHack(UTF8ToWide(url_path));
+ name_with_proper_ext = base::FilePath::FromUTF8Unsafe(url_path);
}
// Ask user for getting final saving name.
diff --git a/chromium/content/browser/download/save_package.h b/chromium/content/browser/download/save_package.h
index b53280d7adf..939002e1eee 100644
--- a/chromium/content/browser/download/save_package.h
+++ b/chromium/content/browser/download/save_package.h
@@ -129,7 +129,7 @@ class CONTENT_EXPORT SavePackage
DownloadItemImpl* item);
// Callback for WebContents::GenerateMHTML().
- void OnMHTMLGenerated(const base::FilePath& path, int64 size);
+ void OnMHTMLGenerated(int64 size);
// For testing only.
SavePackage(WebContents* web_contents,
diff --git a/chromium/content/browser/download/save_package_browsertest.cc b/chromium/content/browser/download/save_package_browsertest.cc
index cfa63edefb2..391033238cd 100644
--- a/chromium/content/browser/download/save_package_browsertest.cc
+++ b/chromium/content/browser/download/save_package_browsertest.cc
@@ -4,7 +4,7 @@
#include "base/files/scoped_temp_dir.h"
#include "content/browser/download/save_package.h"
-#include "content/shell/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
diff --git a/chromium/content/browser/download/save_package_unittest.cc b/chromium/content/browser/download/save_package_unittest.cc
index 9c8f29f46be..c0aa3f8862b 100644
--- a/chromium/content/browser/download/save_package_unittest.cc
+++ b/chromium/content/browser/download/save_package_unittest.cc
@@ -434,7 +434,7 @@ TEST_F(SavePackageTest, TestGetUrlToBeSavedViewSource) {
base::FilePath(kTestDir).Append(file_name));
NavigateAndCommit(view_source_url);
EXPECT_EQ(actual_url, GetUrlToBeSaved());
- EXPECT_EQ(view_source_url, contents()->GetURL());
+ EXPECT_EQ(view_source_url, contents()->GetLastCommittedURL());
}
} // namespace content
diff --git a/chromium/content/browser/fileapi/browser_file_system_helper.cc b/chromium/content/browser/fileapi/browser_file_system_helper.cc
index 6df6f1f381c..094f35ac304 100644
--- a/chromium/content/browser/fileapi/browser_file_system_helper.cc
+++ b/chromium/content/browser/fileapi/browser_file_system_helper.cc
@@ -98,27 +98,6 @@ bool FileSystemURLIsValid(
return context->GetFileSystemBackend(url.type()) != NULL;
}
-bool CheckFileSystemPermissionsForProcess(
- fileapi::FileSystemContext* context, int process_id,
- const fileapi::FileSystemURL& url, int permissions,
- base::PlatformFileError* error) {
- DCHECK(error);
-
- if (!FileSystemURLIsValid(context, url)) {
- *error = base::PLATFORM_FILE_ERROR_INVALID_URL;
- return false;
- }
-
- if (!ChildProcessSecurityPolicyImpl::GetInstance()->
- HasPermissionsForFileSystemFile(process_id, url, permissions)) {
- *error = base::PLATFORM_FILE_ERROR_SECURITY;
- return false;
- }
-
- *error = base::PLATFORM_FILE_OK;
- return true;
-}
-
void SyncGetPlatformPath(fileapi::FileSystemContext* context,
int process_id,
const GURL& path,
diff --git a/chromium/content/browser/fileapi/browser_file_system_helper.h b/chromium/content/browser/fileapi/browser_file_system_helper.h
index ba1e0943628..ad44ced5064 100644
--- a/chromium/content/browser/fileapi/browser_file_system_helper.h
+++ b/chromium/content/browser/fileapi/browser_file_system_helper.h
@@ -32,14 +32,6 @@ CreateFileSystemContext(
CONTENT_EXPORT bool FileSystemURLIsValid(fileapi::FileSystemContext* context,
const fileapi::FileSystemURL& url);
-// Check whether a process has permission to access the file system URL.
-CONTENT_EXPORT bool CheckFileSystemPermissionsForProcess(
- fileapi::FileSystemContext* context,
- int process_id,
- const fileapi::FileSystemURL& url,
- int permissions,
- base::PlatformFileError* error);
-
// Get the platform path from a file system URL. This needs to be called
// on the FILE thread.
CONTENT_EXPORT void SyncGetPlatformPath(fileapi::FileSystemContext* context,
diff --git a/chromium/content/browser/fileapi/chrome_blob_storage_context.cc b/chromium/content/browser/fileapi/chrome_blob_storage_context.cc
index 728b0d58e25..97151a83f67 100644
--- a/chromium/content/browser/fileapi/chrome_blob_storage_context.cc
+++ b/chromium/content/browser/fileapi/chrome_blob_storage_context.cc
@@ -7,10 +7,10 @@
#include "base/bind.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
-#include "webkit/browser/blob/blob_storage_controller.h"
+#include "webkit/browser/blob/blob_storage_context.h"
using base::UserDataAdapter;
-using webkit_blob::BlobStorageController;
+using webkit_blob::BlobStorageContext;
namespace content {
@@ -40,7 +40,7 @@ ChromeBlobStorageContext* ChromeBlobStorageContext::GetFor(
void ChromeBlobStorageContext::InitializeOnIOThread() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- controller_.reset(new BlobStorageController());
+ context_.reset(new BlobStorageContext());
}
ChromeBlobStorageContext::~ChromeBlobStorageContext() {}
diff --git a/chromium/content/browser/fileapi/chrome_blob_storage_context.h b/chromium/content/browser/fileapi/chrome_blob_storage_context.h
index 3992e0e4198..641e2353006 100644
--- a/chromium/content/browser/fileapi/chrome_blob_storage_context.h
+++ b/chromium/content/browser/fileapi/chrome_blob_storage_context.h
@@ -11,7 +11,7 @@
#include "content/common/content_export.h"
namespace webkit_blob {
-class BlobStorageController;
+class BlobStorageContext;
}
namespace content {
@@ -36,8 +36,8 @@ class CONTENT_EXPORT ChromeBlobStorageContext
void InitializeOnIOThread();
- webkit_blob::BlobStorageController* controller() const {
- return controller_.get();
+ webkit_blob::BlobStorageContext* context() const {
+ return context_.get();
}
protected:
@@ -51,7 +51,7 @@ class CONTENT_EXPORT ChromeBlobStorageContext
void DeleteOnCorrectThread() const;
- scoped_ptr<webkit_blob::BlobStorageController> controller_;
+ scoped_ptr<webkit_blob::BlobStorageContext> context_;
};
struct ChromeBlobStorageContextDeleter {
diff --git a/chromium/content/browser/fileapi/file_system_browsertest.cc b/chromium/content/browser/fileapi/file_system_browsertest.cc
index 7c464a36e9f..eafb1b1cfa4 100644
--- a/chromium/content/browser/fileapi/file_system_browsertest.cc
+++ b/chromium/content/browser/fileapi/file_system_browsertest.cc
@@ -13,7 +13,7 @@
#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
-#include "content/shell/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
#include "webkit/browser/quota/quota_manager.h"
@@ -36,7 +36,8 @@ class FileSystemBrowserTest : public ContentBrowserTest {
LOG(INFO) << "Navigating to URL and blocking.";
NavigateToURLBlockUntilNavigationsComplete(the_browser, test_url, 2);
LOG(INFO) << "Navigation done.";
- std::string result = the_browser->web_contents()->GetURL().ref();
+ std::string result =
+ the_browser->web_contents()->GetLastCommittedURL().ref();
if (result != "pass") {
std::string js_result;
ASSERT_TRUE(ExecuteScriptAndExtractString(
diff --git a/chromium/content/browser/fileapi/fileapi_message_filter.cc b/chromium/content/browser/fileapi/fileapi_message_filter.cc
index 5641564cff9..1a79ea2d349 100644
--- a/chromium/content/browser/fileapi/fileapi_message_filter.cc
+++ b/chromium/content/browser/fileapi/fileapi_message_filter.cc
@@ -28,7 +28,8 @@
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "url/gurl.h"
-#include "webkit/browser/blob/blob_storage_controller.h"
+#include "webkit/browser/blob/blob_storage_context.h"
+#include "webkit/browser/blob/blob_storage_host.h"
#include "webkit/browser/fileapi/file_observers.h"
#include "webkit/browser/fileapi/file_permission_policy.h"
#include "webkit/browser/fileapi/file_system_context.h"
@@ -37,9 +38,15 @@
#include "webkit/common/blob/blob_data.h"
#include "webkit/common/blob/shareable_file_reference.h"
#include "webkit/common/fileapi/directory_entry.h"
+#include "webkit/common/fileapi/file_system_info.h"
#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;
@@ -47,7 +54,8 @@ using fileapi::FileSystemURL;
using fileapi::FileUpdateObserver;
using fileapi::UpdateObserverList;
using webkit_blob::BlobData;
-using webkit_blob::BlobStorageController;
+using webkit_blob::BlobStorageContext;
+using webkit_blob::BlobStorageHost;
namespace content {
@@ -68,6 +76,7 @@ FileAPIMessageFilter::FileAPIMessageFilter(
StreamContext* stream_context)
: process_id_(process_id),
context_(file_system_context),
+ security_policy_(ChildProcessSecurityPolicyImpl::GetInstance()),
request_context_getter_(request_context_getter),
request_context_(NULL),
blob_storage_context_(blob_storage_context),
@@ -86,6 +95,7 @@ FileAPIMessageFilter::FileAPIMessageFilter(
StreamContext* stream_context)
: process_id_(process_id),
context_(file_system_context),
+ security_policy_(ChildProcessSecurityPolicyImpl::GetInstance()),
request_context_(request_context),
blob_storage_context_(blob_storage_context),
stream_context_(stream_context) {
@@ -106,6 +116,9 @@ void FileAPIMessageFilter::OnChannelConnected(int32 peer_pid) {
DCHECK(request_context_);
}
+ blob_storage_host_.reset(
+ new BlobStorageHost(blob_storage_context_->context()));
+
operation_runner_ = context_->CreateFileSystemOperationRunner();
}
@@ -115,10 +128,7 @@ void FileAPIMessageFilter::OnChannelClosing() {
// Unregister all the blob and stream URLs that are previously registered in
// this process.
- for (base::hash_set<std::string>::const_iterator iter = blob_urls_.begin();
- iter != blob_urls_.end(); ++iter) {
- blob_storage_context_->controller()->RemoveBlob(GURL(*iter));
- }
+ blob_storage_host_.reset();
for (base::hash_set<std::string>::const_iterator iter = stream_urls_.begin();
iter != stream_urls_.end(); ++iter) {
stream_context_->registry()->UnregisterStream(GURL(*iter));
@@ -159,6 +169,7 @@ bool FileAPIMessageFilter::OnMessageReceived(
bool handled = true;
IPC_BEGIN_MESSAGE_MAP_EX(FileAPIMessageFilter, message, *message_was_ok)
IPC_MESSAGE_HANDLER(FileSystemHostMsg_Open, OnOpen)
+ IPC_MESSAGE_HANDLER(FileSystemHostMsg_ResolveURL, OnResolveURL)
IPC_MESSAGE_HANDLER(FileSystemHostMsg_DeleteFileSystem, OnDeleteFileSystem)
IPC_MESSAGE_HANDLER(FileSystemHostMsg_Move, OnMove)
IPC_MESSAGE_HANDLER(FileSystemHostMsg_Copy, OnCopy)
@@ -168,10 +179,13 @@ bool FileAPIMessageFilter::OnMessageReceived(
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)
- IPC_MESSAGE_HANDLER(FileSystemHostMsg_OpenFile, OnOpenFile)
+#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)
@@ -187,14 +201,26 @@ bool FileAPIMessageFilter::OnMessageReceived(
IPC_MESSAGE_HANDLER(BlobHostMsg_SyncAppendSharedMemory,
OnAppendSharedMemoryToBlob)
IPC_MESSAGE_HANDLER(BlobHostMsg_FinishBuilding, OnFinishBuildingBlob)
- IPC_MESSAGE_HANDLER(BlobHostMsg_Clone, OnCloneBlob)
- IPC_MESSAGE_HANDLER(BlobHostMsg_Remove, OnRemoveBlob)
+ IPC_MESSAGE_HANDLER(BlobHostMsg_IncrementRefCount,
+ OnIncrementBlobRefCount)
+ IPC_MESSAGE_HANDLER(BlobHostMsg_DecrementRefCount,
+ OnDecrementBlobRefCount)
+ 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)
IPC_MESSAGE_HANDLER(StreamHostMsg_SyncAppendSharedMemory,
OnAppendSharedMemoryToStream)
IPC_MESSAGE_HANDLER(StreamHostMsg_FinishBuilding, OnFinishBuildingStream)
+ IPC_MESSAGE_HANDLER(StreamHostMsg_AbortBuilding, OnAbortBuildingStream)
IPC_MESSAGE_HANDLER(StreamHostMsg_Clone, OnCloneStream)
IPC_MESSAGE_HANDLER(StreamHostMsg_Remove, OnRemoveStream)
IPC_MESSAGE_UNHANDLED(handled = false)
@@ -226,6 +252,23 @@ void FileAPIMessageFilter::OnOpen(
&FileAPIMessageFilter::DidOpenFileSystem, this, request_id));
}
+void FileAPIMessageFilter::OnResolveURL(
+ int request_id,
+ const GURL& filesystem_url) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ FileSystemURL url(context_->CrackURL(filesystem_url));
+ if (!ValidateFileSystemURL(request_id, url))
+ return;
+ if (!security_policy_->CanReadFileSystemFile(process_id_, url)) {
+ Send(new FileSystemMsg_DidFail(request_id,
+ base::PLATFORM_FILE_ERROR_SECURITY));
+ return;
+ }
+
+ context_->ResolveURL(url, base::Bind(
+ &FileAPIMessageFilter::DidResolveURL, this, request_id));
+}
+
void FileAPIMessageFilter::OnDeleteFileSystem(
int request_id,
const GURL& origin_url,
@@ -238,15 +281,17 @@ void FileAPIMessageFilter::OnDeleteFileSystem(
void FileAPIMessageFilter::OnMove(
int request_id, const GURL& src_path, const GURL& dest_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- base::PlatformFileError error;
FileSystemURL src_url(context_->CrackURL(src_path));
FileSystemURL dest_url(context_->CrackURL(dest_path));
- const int src_permissions =
- fileapi::kReadFilePermissions | fileapi::kWriteFilePermissions;
- if (!HasPermissionsForFile(src_url, src_permissions, &error) ||
- !HasPermissionsForFile(
- dest_url, fileapi::kCreateFilePermissions, &error)) {
- Send(new FileSystemMsg_DidFail(request_id, error));
+ if (!ValidateFileSystemURL(request_id, src_url) ||
+ !ValidateFileSystemURL(request_id, dest_url)) {
+ return;
+ }
+ if (!security_policy_->CanReadFileSystemFile(process_id_, src_url) ||
+ !security_policy_->CanWriteFileSystemFile(process_id_, src_url) ||
+ !security_policy_->CanCreateFileSystemFile(process_id_, dest_url)) {
+ Send(new FileSystemMsg_DidFail(request_id,
+ base::PLATFORM_FILE_ERROR_SECURITY));
return;
}
@@ -258,28 +303,34 @@ void FileAPIMessageFilter::OnMove(
void FileAPIMessageFilter::OnCopy(
int request_id, const GURL& src_path, const GURL& dest_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- base::PlatformFileError error;
FileSystemURL src_url(context_->CrackURL(src_path));
FileSystemURL dest_url(context_->CrackURL(dest_path));
- if (!HasPermissionsForFile(src_url, fileapi::kReadFilePermissions, &error) ||
- !HasPermissionsForFile(
- dest_url, fileapi::kCreateFilePermissions, &error)) {
- Send(new FileSystemMsg_DidFail(request_id, error));
+ if (!ValidateFileSystemURL(request_id, src_url) ||
+ !ValidateFileSystemURL(request_id, dest_url)) {
+ return;
+ }
+ if (!security_policy_->CanReadFileSystemFile(process_id_, src_url) ||
+ !security_policy_->CanCreateFileSystemFile(process_id_, dest_url)) {
+ Send(new FileSystemMsg_DidFail(request_id,
+ base::PLATFORM_FILE_ERROR_SECURITY));
return;
}
operations_[request_id] = operation_runner()->Copy(
src_url, dest_url,
+ fileapi::FileSystemOperationRunner::CopyProgressCallback(),
base::Bind(&FileAPIMessageFilter::DidFinish, this, request_id));
}
void FileAPIMessageFilter::OnRemove(
int request_id, const GURL& path, bool recursive) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- base::PlatformFileError error;
FileSystemURL url(context_->CrackURL(path));
- if (!HasPermissionsForFile(url, fileapi::kWriteFilePermissions, &error)) {
- Send(new FileSystemMsg_DidFail(request_id, error));
+ if (!ValidateFileSystemURL(request_id, url))
+ return;
+ if (!security_policy_->CanWriteFileSystemFile(process_id_, url)) {
+ Send(new FileSystemMsg_DidFail(request_id,
+ base::PLATFORM_FILE_ERROR_SECURITY));
return;
}
@@ -291,10 +342,12 @@ void FileAPIMessageFilter::OnRemove(
void FileAPIMessageFilter::OnReadMetadata(
int request_id, const GURL& path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- base::PlatformFileError error;
FileSystemURL url(context_->CrackURL(path));
- if (!HasPermissionsForFile(url, fileapi::kReadFilePermissions, &error)) {
- Send(new FileSystemMsg_DidFail(request_id, error));
+ if (!ValidateFileSystemURL(request_id, url))
+ return;
+ if (!security_policy_->CanReadFileSystemFile(process_id_, url)) {
+ Send(new FileSystemMsg_DidFail(request_id,
+ base::PLATFORM_FILE_ERROR_SECURITY));
return;
}
@@ -306,10 +359,12 @@ void FileAPIMessageFilter::OnCreate(
int request_id, const GURL& path, bool exclusive,
bool is_directory, bool recursive) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- base::PlatformFileError error;
FileSystemURL url(context_->CrackURL(path));
- if (!HasPermissionsForFile(url, fileapi::kCreateFilePermissions, &error)) {
- Send(new FileSystemMsg_DidFail(request_id, error));
+ if (!ValidateFileSystemURL(request_id, url))
+ return;
+ if (!security_policy_->CanCreateFileSystemFile(process_id_, url)) {
+ Send(new FileSystemMsg_DidFail(request_id,
+ base::PLATFORM_FILE_ERROR_SECURITY));
return;
}
@@ -327,10 +382,12 @@ void FileAPIMessageFilter::OnCreate(
void FileAPIMessageFilter::OnExists(
int request_id, const GURL& path, bool is_directory) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- base::PlatformFileError error;
FileSystemURL url(context_->CrackURL(path));
- if (!HasPermissionsForFile(url, fileapi::kReadFilePermissions, &error)) {
- Send(new FileSystemMsg_DidFail(request_id, error));
+ if (!ValidateFileSystemURL(request_id, url))
+ return;
+ if (!security_policy_->CanReadFileSystemFile(process_id_, url)) {
+ Send(new FileSystemMsg_DidFail(request_id,
+ base::PLATFORM_FILE_ERROR_SECURITY));
return;
}
@@ -348,10 +405,12 @@ void FileAPIMessageFilter::OnExists(
void FileAPIMessageFilter::OnReadDirectory(
int request_id, const GURL& path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- base::PlatformFileError error;
FileSystemURL url(context_->CrackURL(path));
- if (!HasPermissionsForFile(url, fileapi::kReadFilePermissions, &error)) {
- Send(new FileSystemMsg_DidFail(request_id, error));
+ if (!ValidateFileSystemURL(request_id, url))
+ return;
+ if (!security_policy_->CanReadFileSystemFile(process_id_, url)) {
+ Send(new FileSystemMsg_DidFail(request_id,
+ base::PLATFORM_FILE_ERROR_SECURITY));
return;
}
@@ -360,11 +419,21 @@ void FileAPIMessageFilter::OnReadDirectory(
this, request_id));
}
-void FileAPIMessageFilter::OnWrite(
+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,
+ const std::string& blob_uuid,
+ int64 offset) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (!request_context_) {
// We can't write w/o a request context, trying to do so will crash.
@@ -373,14 +442,19 @@ void FileAPIMessageFilter::OnWrite(
}
FileSystemURL url(context_->CrackURL(path));
- base::PlatformFileError error;
- if (!HasPermissionsForFile(url, fileapi::kWriteFilePermissions, &error)) {
- Send(new FileSystemMsg_DidFail(request_id, error));
+ if (!ValidateFileSystemURL(request_id, url))
+ return;
+ if (!security_policy_->CanWriteFileSystemFile(process_id_, url)) {
+ Send(new FileSystemMsg_DidFail(request_id,
+ base::PLATFORM_FILE_ERROR_SECURITY));
return;
}
+ scoped_ptr<webkit_blob::BlobDataHandle> blob =
+ blob_storage_context_->context()->GetBlobDataFromUUID(blob_uuid);
+
operations_[request_id] = operation_runner()->Write(
- request_context_, url, blob_url, offset,
+ request_context_, url, blob.Pass(), offset,
base::Bind(&FileAPIMessageFilter::DidWrite, this, request_id));
}
@@ -388,10 +462,12 @@ void FileAPIMessageFilter::OnTruncate(
int request_id,
const GURL& path,
int64 length) {
- base::PlatformFileError error;
FileSystemURL url(context_->CrackURL(path));
- if (!HasPermissionsForFile(url, fileapi::kWriteFilePermissions, &error)) {
- Send(new FileSystemMsg_DidFail(request_id, error));
+ if (!ValidateFileSystemURL(request_id, url))
+ return;
+ if (!security_policy_->CanWriteFileSystemFile(process_id_, url)) {
+ Send(new FileSystemMsg_DidFail(request_id,
+ base::PLATFORM_FILE_ERROR_SECURITY));
return;
}
@@ -407,9 +483,11 @@ void FileAPIMessageFilter::OnTouchFile(
const base::Time& last_modified_time) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
FileSystemURL url(context_->CrackURL(path));
- base::PlatformFileError error;
- if (!HasPermissionsForFile(url, fileapi::kCreateFilePermissions, &error)) {
- Send(new FileSystemMsg_DidFail(request_id, error));
+ if (!ValidateFileSystemURL(request_id, url))
+ return;
+ if (!security_policy_->CanCreateFileSystemFile(process_id_, url)) {
+ Send(new FileSystemMsg_DidFail(request_id,
+ base::PLATFORM_FILE_ERROR_SECURITY));
return;
}
@@ -437,14 +515,16 @@ void FileAPIMessageFilter::OnCancel(
}
}
-void FileAPIMessageFilter::OnOpenFile(
- int request_id, const GURL& path, int file_flags) {
+#if defined(ENABLE_PLUGINS)
+void FileAPIMessageFilter::OnOpenPepperFile(
+ int request_id, const GURL& path, int pp_open_flags) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- base::PlatformFileError error;
- const int open_permissions = file_flags & fileapi::kOpenPepperFilePermissions;
- FileSystemURL url(context_->CrackURL(path));
- if (!HasPermissionsForFile(url, open_permissions, &error)) {
- Send(new FileSystemMsg_DidFail(request_id, error));
+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;
}
@@ -461,11 +541,19 @@ void FileAPIMessageFilter::OnOpenFile(
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, open_permissions, PeerHandle(),
+ 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));
@@ -518,9 +606,11 @@ void FileAPIMessageFilter::OnCreateSnapshotFile(
// Make sure if this file can be read by the renderer as this is
// called when the renderer is about to create a new File object
// (for reading the file).
- base::PlatformFileError error;
- if (!HasPermissionsForFile(url, fileapi::kReadFilePermissions, &error)) {
- Send(new FileSystemMsg_DidFail(request_id, error));
+ if (!ValidateFileSystemURL(request_id, url))
+ return;
+ if (!security_policy_->CanReadFileSystemFile(process_id_, url)) {
+ Send(new FileSystemMsg_DidFail(request_id,
+ base::PLATFORM_FILE_ERROR_SECURITY));
return;
}
@@ -535,39 +625,38 @@ void FileAPIMessageFilter::OnDidReceiveSnapshotFile(int request_id) {
in_transit_snapshot_files_.erase(request_id);
}
-void FileAPIMessageFilter::OnStartBuildingBlob(const GURL& url) {
+void FileAPIMessageFilter::OnStartBuildingBlob(const std::string& uuid) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- blob_storage_context_->controller()->StartBuildingBlob(url);
- blob_urls_.insert(url.spec());
+ ignore_result(blob_storage_host_->StartBuildingBlob(uuid));
}
void FileAPIMessageFilter::OnAppendBlobDataItemToBlob(
- const GURL& url, const BlobData::Item& item) {
+ const std::string& uuid, const BlobData::Item& item) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (item.type() == BlobData::Item::TYPE_FILE_FILESYSTEM) {
- base::PlatformFileError error;
- FileSystemURL filesystem_url(context_->CrackURL(item.url()));
- if (!HasPermissionsForFile(filesystem_url,
- fileapi::kReadFilePermissions, &error)) {
- OnRemoveBlob(url);
+ FileSystemURL filesystem_url(context_->CrackURL(item.filesystem_url()));
+ if (!FileSystemURLIsValid(context_, filesystem_url) ||
+ !security_policy_->CanReadFileSystemFile(process_id_, filesystem_url)) {
+ ignore_result(blob_storage_host_->CancelBuildingBlob(uuid));
return;
}
}
if (item.type() == BlobData::Item::TYPE_FILE &&
- !ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
- process_id_, item.path())) {
- OnRemoveBlob(url);
+ !security_policy_->CanReadFile(process_id_, item.path())) {
+ ignore_result(blob_storage_host_->CancelBuildingBlob(uuid));
return;
}
if (item.length() == 0) {
BadMessageReceived();
return;
}
- blob_storage_context_->controller()->AppendBlobDataItem(url, item);
+ ignore_result(blob_storage_host_->AppendBlobDataItem(uuid, item));
}
void FileAPIMessageFilter::OnAppendSharedMemoryToBlob(
- const GURL& url, base::SharedMemoryHandle handle, size_t buffer_size) {
+ const std::string& uuid,
+ base::SharedMemoryHandle handle,
+ size_t buffer_size) {
DCHECK(base::SharedMemory::IsHandleValid(handle));
if (!buffer_size) {
BadMessageReceived();
@@ -579,33 +668,59 @@ void FileAPIMessageFilter::OnAppendSharedMemoryToBlob(
base::SharedMemory shared_memory(handle, true);
#endif
if (!shared_memory.Map(buffer_size)) {
- OnRemoveBlob(url);
+ ignore_result(blob_storage_host_->CancelBuildingBlob(uuid));
return;
}
BlobData::Item item;
item.SetToSharedBytes(static_cast<char*>(shared_memory.memory()),
buffer_size);
- blob_storage_context_->controller()->AppendBlobDataItem(url, item);
+ ignore_result(blob_storage_host_->AppendBlobDataItem(uuid, item));
}
void FileAPIMessageFilter::OnFinishBuildingBlob(
- const GURL& url, const std::string& content_type) {
+ const std::string& uuid, const std::string& content_type) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ ignore_result(blob_storage_host_->FinishBuildingBlob(uuid, content_type));
+ // TODO(michaeln): check return values once blink has migrated, crbug/174200
+}
+
+void FileAPIMessageFilter::OnIncrementBlobRefCount(const std::string& uuid) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ ignore_result(blob_storage_host_->IncrementBlobRefCount(uuid));
+}
+
+void FileAPIMessageFilter::OnDecrementBlobRefCount(const std::string& uuid) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ ignore_result(blob_storage_host_->DecrementBlobRefCount(uuid));
+}
+
+void FileAPIMessageFilter::OnRegisterPublicBlobURL(
+ const GURL& public_url, const std::string& uuid) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ ignore_result(blob_storage_host_->RegisterPublicBlobURL(public_url, uuid));
+}
+
+void FileAPIMessageFilter::OnRevokePublicBlobURL(const GURL& public_url) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ 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_context_->controller()->FinishBuildingBlob(url, content_type);
+ blob_storage_host_->DeprecatedRegisterBlobURL(url, uuid);
}
-void FileAPIMessageFilter::OnCloneBlob(
+void FileAPIMessageFilter::OnDeprecatedCloneBlobURL(
const GURL& url, const GURL& src_url) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- blob_storage_context_->controller()->CloneBlob(url, src_url);
- blob_urls_.insert(url.spec());
+ blob_storage_host_->DeprecatedCloneBlobURL(url, src_url);
}
-void FileAPIMessageFilter::OnRemoveBlob(const GURL& url) {
+void FileAPIMessageFilter::OnDeprecatedRevokeBlobURL(const GURL& url) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- blob_storage_context_->controller()->RemoveBlob(url);
- blob_urls_.erase(url.spec());
+ blob_storage_host_->DeprecatedRevokeBlobURL(url);
}
void FileAPIMessageFilter::OnStartBuildingStream(
@@ -631,10 +746,10 @@ void FileAPIMessageFilter::OnAppendBlobDataItemToStream(
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
scoped_refptr<Stream> stream(GetStreamForURL(url));
- if (!stream.get()) {
- NOTREACHED();
+ // Stream instances may be deleted on error. Just abort if there's no Stream
+ // instance for |url| in the registry.
+ if (!stream.get())
return;
- }
// Data for stream is delivered as TYPE_BYTES item.
if (item.type() != BlobData::Item::TYPE_BYTES) {
@@ -662,10 +777,8 @@ void FileAPIMessageFilter::OnAppendSharedMemoryToStream(
}
scoped_refptr<Stream> stream(GetStreamForURL(url));
- if (!stream.get()) {
- NOTREACHED();
+ if (!stream.get())
return;
- }
stream->AddData(static_cast<char*>(shared_memory.memory()), buffer_size);
}
@@ -675,17 +788,22 @@ void FileAPIMessageFilter::OnFinishBuildingStream(const GURL& url) {
scoped_refptr<Stream> stream(GetStreamForURL(url));
if (stream.get())
stream->Finalize();
- else
- NOTREACHED();
+}
+
+void FileAPIMessageFilter::OnAbortBuildingStream(const GURL& url) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ scoped_refptr<Stream> stream(GetStreamForURL(url));
+ if (stream.get())
+ stream->Abort();
}
void FileAPIMessageFilter::OnCloneStream(
const GURL& url, const GURL& src_url) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- if (!GetStreamForURL(src_url)) {
- NOTREACHED();
+ // Abort if there's no Stream instance for |src_url| (source Stream which
+ // we're going to make |url| point to) in the registry.
+ if (!GetStreamForURL(src_url))
return;
- }
stream_context_->registry()->CloneStream(url, src_url);
stream_urls_.insert(url.spec());
@@ -694,10 +812,8 @@ void FileAPIMessageFilter::OnCloneStream(
void FileAPIMessageFilter::OnRemoveStream(const GURL& url) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- if (!GetStreamForURL(url).get()) {
- NOTREACHED();
+ if (!GetStreamForURL(url).get())
return;
- }
stream_context_->registry()->UnregisterStream(url);
stream_urls_.erase(url.spec());
@@ -776,18 +892,35 @@ void FileAPIMessageFilter::DidWrite(int request_id,
void FileAPIMessageFilter::DidOpenFileSystem(int request_id,
base::PlatformFileError result,
- const std::string& name,
+ const std::string& filesystem_name,
const GURL& root) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (result == base::PLATFORM_FILE_OK) {
DCHECK(root.is_valid());
- Send(new FileSystemMsg_DidOpenFileSystem(request_id, name, root));
+ Send(new FileSystemMsg_DidOpenFileSystem(
+ request_id, filesystem_name, root));
} else {
Send(new FileSystemMsg_DidFail(request_id, result));
}
// For OpenFileSystem we do not create a new operation, so no unregister here.
}
+void FileAPIMessageFilter::DidResolveURL(int request_id,
+ base::PlatformFileError result,
+ const fileapi::FileSystemInfo& info,
+ const base::FilePath& file_path,
+ bool is_directory) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (result == base::PLATFORM_FILE_OK) {
+ DCHECK(info.root_url.is_valid());
+ Send(new FileSystemMsg_DidResolveURL(
+ request_id, info, file_path, is_directory));
+ } else {
+ Send(new FileSystemMsg_DidFail(request_id, result));
+ }
+ // For ResolveURL we do not create a new operation, so no unregister here.
+}
+
void FileAPIMessageFilter::DidDeleteFileSystem(
int request_id,
base::PlatformFileError result) {
@@ -805,7 +938,7 @@ void FileAPIMessageFilter::DidCreateSnapshot(
base::PlatformFileError result,
const base::PlatformFileInfo& info,
const base::FilePath& platform_path,
- const scoped_refptr<webkit_blob::ShareableFileReference>& snapshot_file) {
+ const scoped_refptr<webkit_blob::ShareableFileReference>& /* unused */) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
operations_.erase(request_id);
@@ -814,17 +947,16 @@ void FileAPIMessageFilter::DidCreateSnapshot(
return;
}
- scoped_refptr<webkit_blob::ShareableFileReference> file_ref = snapshot_file;
- if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
- process_id_, platform_path)) {
+ scoped_refptr<webkit_blob::ShareableFileReference> file_ref =
+ webkit_blob::ShareableFileReference::Get(platform_path);
+ if (!security_policy_->CanReadFile(process_id_, platform_path)) {
// Give per-file read permission to the snapshot file if it hasn't it yet.
// In order for the renderer to be able to read the file via File object,
// it must be granted per-file read permission for the file's platform
// path. By now, it has already been verified that the renderer has
// sufficient permissions to read the file, so giving per-file permission
// here must be safe.
- ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
- process_id_, platform_path);
+ security_policy_->GrantReadFile(process_id_, platform_path);
// Revoke all permissions for the file when the last ref of the file
// is dropped.
@@ -849,10 +981,13 @@ void FileAPIMessageFilter::DidCreateSnapshot(
request_id, info, platform_path));
}
-bool FileAPIMessageFilter::HasPermissionsForFile(
- const FileSystemURL& url, int permissions, base::PlatformFileError* error) {
- return CheckFileSystemPermissionsForProcess(context_, process_id_, url,
- permissions, error);
+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;
}
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 8680f24a998..e9a707f4ac4 100644
--- a/chromium/content/browser/fileapi/fileapi_message_filter.h
+++ b/chromium/content/browser/fileapi/fileapi_message_filter.h
@@ -37,6 +37,7 @@ class FileSystemURL;
class FileSystemContext;
class FileSystemOperationRunner;
struct DirectoryEntry;
+struct FileSystemInfo;
}
namespace net {
@@ -45,10 +46,12 @@ class URLRequestContextGetter;
} // namespace net
namespace webkit_blob {
+class BlobStorageHost;
class ShareableFileReference;
}
namespace content {
+class ChildProcessSecurityPolicyImpl;
class ChromeBlobStorageContext;
// TODO(tyoshino): Factor out code except for IPC gluing from
@@ -91,6 +94,8 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
fileapi::FileSystemType type,
int64 requested_size,
bool create);
+ void OnResolveURL(int request_id,
+ const GURL& filesystem_url);
void OnDeleteFileSystem(int request_id,
const GURL& origin_url,
fileapi::FileSystemType type);
@@ -111,6 +116,11 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
void OnReadDirectory(int request_id, const GURL& path);
void OnWrite(int request_id,
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);
@@ -119,7 +129,9 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
const base::Time& last_access_time,
const base::Time& last_modified_time);
void OnCancel(int request_id, int request_to_cancel);
- void OnOpenFile(int request_id, const GURL& path, int file_flags);
+#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);
@@ -131,14 +143,26 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
// Handlers for BlobHostMsg_ family messages.
- void OnStartBuildingBlob(const GURL& url);
- void OnAppendBlobDataItemToBlob(
- const GURL& url, const webkit_blob::BlobData::Item& item);
- void OnAppendSharedMemoryToBlob(
- const GURL& url, base::SharedMemoryHandle handle, size_t buffer_size);
- void OnFinishBuildingBlob(const GURL& url, const std::string& content_type);
- void OnCloneBlob(const GURL& url, const GURL& src_url);
- void OnRemoveBlob(const GURL& url);
+ void OnStartBuildingBlob(const std::string& uuid);
+ void OnAppendBlobDataItemToBlob(const std::string& uuid,
+ const webkit_blob::BlobData::Item& item);
+ void OnAppendSharedMemoryToBlob(const std::string& uuid,
+ base::SharedMemoryHandle handle,
+ size_t buffer_size);
+ void OnFinishBuildingBlob(const std::string& uuid,
+ const std::string& content_type);
+ void OnCancelBuildingBlob(const std::string& uuid);
+ void OnIncrementBlobRefCount(const std::string& uuid);
+ void OnDecrementBlobRefCount(const std::string& uuid);
+ 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.
//
@@ -154,6 +178,7 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
void OnAppendSharedMemoryToStream(
const GURL& url, base::SharedMemoryHandle handle, size_t buffer_size);
void OnFinishBuildingStream(const GURL& url);
+ void OnAbortBuildingStream(const GURL& url);
void OnCloneStream(const GURL& url, const GURL& src_url);
void OnRemoveStream(const GURL& url);
@@ -179,8 +204,13 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
bool complete);
void DidOpenFileSystem(int request_id,
base::PlatformFileError result,
- const std::string& name,
+ const std::string& filesystem_name,
const GURL& root);
+ void DidResolveURL(int request_id,
+ base::PlatformFileError result,
+ const fileapi::FileSystemInfo& info,
+ const base::FilePath& file_path,
+ bool is_directory);
void DidDeleteFileSystem(int request_id,
base::PlatformFileError result);
void DidCreateSnapshot(
@@ -191,12 +221,12 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
const base::FilePath& platform_path,
const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref);
- // Checks renderer's access permissions for single file.
- bool HasPermissionsForFile(const fileapi::FileSystemURL& url,
- int permissions,
- base::PlatformFileError* error);
+ // Sends a FileSystemMsg_DidFail and returns false if |url| is invalid.
+ bool ValidateFileSystemURL(int request_id, const fileapi::FileSystemURL& url);
- // Retrieves the Stream object for |url| from |stream_context_|.
+ // Retrieves the Stream object for |url| from |stream_context_|. Returns unset
+ // scoped_refptr when there's no Stream instance for the given |url|
+ // registered with stream_context_->registry().
scoped_refptr<Stream> GetStreamForURL(const GURL& url);
fileapi::FileSystemOperationRunner* operation_runner() {
@@ -206,6 +236,7 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
int process_id_;
fileapi::FileSystemContext* context_;
+ ChildProcessSecurityPolicyImpl* security_policy_;
// Keeps map from request_id to OperationID for ongoing operations.
// (Primarily for Cancel operation)
@@ -222,9 +253,9 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
scoped_ptr<fileapi::FileSystemOperationRunner> operation_runner_;
- // Keep track of blob URLs registered in this process. Need to unregister
- // all of them when the renderer process dies.
- base::hash_set<std::string> blob_urls_;
+ // Keeps track of blobs used in this process and cleans up
+ // when the renderer process dies.
+ scoped_ptr<webkit_blob::BlobStorageHost> blob_storage_host_;
// Keep track of stream URLs registered in this process. Need to unregister
// all of them when the renderer process dies.
diff --git a/chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc b/chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc
index 06b112ba64d..90e422c7da6 100644
--- a/chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc
+++ b/chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc
@@ -23,7 +23,7 @@
#include "content/public/test/test_browser_thread.h"
#include "net/base/io_buffer.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/blob/blob_storage_controller.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"
@@ -95,34 +95,6 @@ class FileAPIMessageFilterTest : public testing::Test {
scoped_refptr<FileAPIMessageFilter> filter_;
};
-TEST_F(FileAPIMessageFilterTest, BuildEmptyBlob) {
- webkit_blob::BlobStorageController* controller =
- blob_storage_context_->controller();
-
- const GURL kUrl("blob:foobar");
- const GURL kDifferentUrl("blob:barfoo");
-
- EXPECT_EQ(NULL, controller->GetBlobDataFromUrl(kUrl));
-
- BlobHostMsg_StartBuilding start_message(kUrl);
- EXPECT_TRUE(InvokeOnMessageReceived(start_message));
-
- // Blob is still being built. Nothing should be returned.
- EXPECT_EQ(NULL, controller->GetBlobDataFromUrl(kUrl));
-
- BlobHostMsg_FinishBuilding finish_message(kUrl, kFakeContentType);
- EXPECT_TRUE(InvokeOnMessageReceived(finish_message));
-
- // Now, Blob is built.
- webkit_blob::BlobData* blob_data = controller->GetBlobDataFromUrl(kUrl);
- ASSERT_FALSE(blob_data == NULL);
- EXPECT_EQ(0U, blob_data->items().size());
- EXPECT_EQ(kFakeContentType, blob_data->content_type());
-
- // Nothing should be returned for a URL we didn't use.
- EXPECT_TRUE(controller->GetBlobDataFromUrl(kDifferentUrl) == NULL);
-}
-
TEST_F(FileAPIMessageFilterTest, CloseChannelWithInflightRequest) {
scoped_refptr<FileAPIMessageFilter> filter(
new FileAPIMessageFilter(
@@ -190,14 +162,10 @@ TEST_F(FileAPIMessageFilterTest, MultipleFilters) {
TEST_F(FileAPIMessageFilterTest, BuildEmptyStream) {
StreamRegistry* stream_registry = stream_context_->registry();
- webkit_blob::BlobStorageController* blob_controller =
- blob_storage_context_->controller();
-
const GURL kUrl(kFakeBlobInternalUrlSpec);
const GURL kDifferentUrl("blob:barfoo");
EXPECT_EQ(NULL, stream_registry->GetStream(kUrl).get());
- EXPECT_EQ(NULL, blob_controller->GetBlobDataFromUrl(kUrl));
StreamHostMsg_StartBuilding start_message(kUrl, kFakeContentType);
EXPECT_TRUE(InvokeOnMessageReceived(start_message));
@@ -217,9 +185,6 @@ TEST_F(FileAPIMessageFilterTest, BuildEmptyStream) {
StreamHostMsg_FinishBuilding finish_message(kUrl);
EXPECT_TRUE(InvokeOnMessageReceived(finish_message));
- // Blob controller shouldn't be affected.
- EXPECT_EQ(NULL, blob_controller->GetBlobDataFromUrl(kUrl));
-
stream = stream_registry->GetStream(kUrl);
ASSERT_FALSE(stream.get() == NULL);
EXPECT_EQ(Stream::STREAM_EMPTY,
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 d59ac180aa8..91ebdf56519 100644
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc
+++ b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc
@@ -212,17 +212,9 @@ BOOL CALLBACK DirectInputEnumDevicesCallback(const DIDEVICEINSTANCE* instance,
GamepadPlatformDataFetcherWin::GamepadPlatformDataFetcherWin()
: xinput_dll_(base::FilePath(FILE_PATH_LITERAL("xinput1_3.dll"))),
xinput_available_(GetXInputDllFunctions()) {
- // TODO(teravest): http://crbug.com/260187
- if (base::win::GetVersion() > base::win::VERSION_XP) {
- directinput_available_ = SUCCEEDED(DirectInput8Create(
- GetModuleHandle(NULL),
- DIRECTINPUT_VERSION,
- IID_IDirectInput8,
- reinterpret_cast<void**>(&directinput_interface_),
- NULL));
- } else {
- directinput_available_ = false;
- }
+ // TODO(teravest): http://crbug.com/260187 for Windows XP.
+ // TODO(teravest): http://crbug.com/305267 for later versions of windows.
+ directinput_available_ = false;
for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i)
pad_state_[i].status = DISCONNECTED;
}
diff --git a/chromium/content/browser/geolocation/core_location_data_provider_mac.h b/chromium/content/browser/geolocation/core_location_data_provider_mac.h
deleted file mode 100644
index 29204aa0d8c..00000000000
--- a/chromium/content/browser/geolocation/core_location_data_provider_mac.h
+++ /dev/null
@@ -1,54 +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 a CoreLocation data provider class that allows the
-// CoreLocation framework to run on the UI thread, since the Geolocation API's
-// providers all live on the IO thread
-
-#ifndef CONTENT_BROWSER_GEOLOCATION_CORE_LOCATION_DATA_PROVIDER_H_
-#define CONTENT_BROWSER_GEOLOCATION_CORE_LOCATION_DATA_PROVIDER_H_
-
-#include "base/mac/scoped_nsobject.h"
-#include "base/memory/ref_counted.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/common/geoposition.h"
-
-#import <Foundation/Foundation.h>
-
-@class CoreLocationWrapperMac;
-
-namespace content {
-class CoreLocationProviderMac;
-
-// Data provider class that allows CoreLocation to run in Chrome's UI thread
-// while existing on any of Chrome's threads (in this case the IO thread)
-class CoreLocationDataProviderMac
- : public base::RefCountedThreadSafe<CoreLocationDataProviderMac> {
- public:
- CoreLocationDataProviderMac();
-
- bool StartUpdating(CoreLocationProviderMac* provider);
- void StopUpdating();
-
- void UpdatePosition(Geoposition* position);
-
- private:
- friend class base::RefCountedThreadSafe<CoreLocationDataProviderMac>;
- ~CoreLocationDataProviderMac();
-
- // These must execute in BrowserThread::UI
- void StartUpdatingTask();
- void StopUpdatingTask();
- // This must execute in the origin thread (IO thread)
- void PositionUpdated(Geoposition position);
-
- // The wrapper class that supplies this class with position data
- base::scoped_nsobject<CoreLocationWrapperMac> wrapper_;
- // The LocationProvider class that should receive position data
- CoreLocationProviderMac* provider_;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_GEOLOCATION_CORE_LOCATION_DATA_PROVIDER_H_
diff --git a/chromium/content/browser/geolocation/core_location_data_provider_mac.mm b/chromium/content/browser/geolocation/core_location_data_provider_mac.mm
deleted file mode 100644
index 8b1cf82c28b..00000000000
--- a/chromium/content/browser/geolocation/core_location_data_provider_mac.mm
+++ /dev/null
@@ -1,256 +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 contains the class definitions for the CoreLocation data provider
-// class and the accompanying Objective C wrapper class. This data provider
-// is used to allow the CoreLocation wrapper to run on the UI thread, since
-// CLLocationManager's start and stop updating methods must be called from a
-// thread with an active NSRunLoop. Currently only the UI thread appears to
-// fill that requirement.
-
-#include "content/browser/geolocation/core_location_data_provider_mac.h"
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/time/time.h"
-#include "content/browser/geolocation/core_location_provider_mac.h"
-#include "content/browser/geolocation/geolocation_provider_impl.h"
-
-using content::CoreLocationDataProviderMac;
-using content::Geoposition;
-
-// A few required declarations since the CoreLocation headers are not available
-// with the Mac OS X 10.5 SDK.
-// TODO(jorgevillatoro): Remove these declarations when we build against 10.6
-
-// This idea was borrowed from wifi_data_provider_corewlan_mac.mm
-typedef double CLLocationDegrees;
-typedef double CLLocationAccuracy;
-typedef double CLLocationSpeed;
-typedef double CLLocationDirection;
-typedef double CLLocationDistance;
-typedef struct {
- CLLocationDegrees latitude;
- CLLocationDegrees longitude;
-} CLLocationCoordinate2D;
-
-enum {
- kCLErrorLocationUnknown = 0,
- kCLErrorDenied
-};
-
-@interface CLLocationManager : NSObject
-+ (BOOL)locationServicesEnabled;
-@property(assign) id delegate;
-- (void)startUpdatingLocation;
-- (void)stopUpdatingLocation;
-@end
-
-@interface CLLocation : NSObject<NSCopying, NSCoding>
-@property(readonly) CLLocationCoordinate2D coordinate;
-@property(readonly) CLLocationDistance altitude;
-@property(readonly) CLLocationAccuracy horizontalAccuracy;
-@property(readonly) CLLocationAccuracy verticalAccuracy;
-@property(readonly) CLLocationDirection course;
-@property(readonly) CLLocationSpeed speed;
-@end
-
-@protocol CLLocationManagerDelegate
-- (void)locationManager:(CLLocationManager*)manager
- didUpdateToLocation:(CLLocation*)newLocation
- fromLocation:(CLLocation*)oldLocation;
-- (void)locationManager:(CLLocationManager*)manager
- didFailWithError:(NSError*)error;
-@end
-
-// This wrapper class receives CLLocation objects from CoreLocation, converts
-// them to Geoposition objects, and passes them on to the data provider class
-// Note: This class has some specific threading requirements, inherited from
-// CLLocationManager. The location manaager's start and stop updating
-// methods must be called from a thread that has an active run loop (which
-// seems to only be the UI thread)
-@interface CoreLocationWrapperMac : NSObject<CLLocationManagerDelegate>
-{
- @private
- NSBundle* bundle_;
- Class locationManagerClass_;
- id locationManager_;
- CoreLocationDataProviderMac* dataProvider_;
-}
-
-- (id)initWithDataProvider:(CoreLocationDataProviderMac*)dataProvider;
-- (void)dealloc;
-
-// Can be called from any thread since it does not require an NSRunLoop. However
-// it is not threadsafe to receive concurrent calls until after a first
-// successful call (to avoid |bundle_| being double initialized)
-- (BOOL)locationDataAvailable;
-
-// These should always be called from BrowserThread::UI
-- (void)startLocation;
-- (void)stopLocation;
-
-// These should only be called by CLLocationManager
-- (void)locationManager:(CLLocationManager*)manager
- didUpdateToLocation:(CLLocation*)newLocation
- fromLocation:(CLLocation*)oldLocation;
-- (void)locationManager:(CLLocationManager*)manager
- didFailWithError:(NSError*)error;
-- (BOOL)loadCoreLocationBundle;
-
-@end
-
-@implementation CoreLocationWrapperMac
-
-- (id)initWithDataProvider:(CoreLocationDataProviderMac*)dataProvider {
- DCHECK(dataProvider);
- dataProvider_ = dataProvider;
- self = [super init];
- return self;
-}
-
-- (void)dealloc {
- [locationManager_ setDelegate:nil];
- [locationManager_ release];
- [locationManagerClass_ release];
- [bundle_ release];
- [super dealloc];
-}
-
-// Load the bundle and check to see if location services are enabled
-// but don't do anything else
-- (BOOL)locationDataAvailable {
- return ([self loadCoreLocationBundle] &&
- [locationManagerClass_ locationServicesEnabled]);
-}
-
-- (void)startLocation {
- if ([self locationDataAvailable]) {
- if (!locationManager_) {
- locationManager_ = [[locationManagerClass_ alloc] init];
- [locationManager_ setDelegate:self];
- }
- [locationManager_ startUpdatingLocation];
- }
-}
-
-- (void)stopLocation {
- [locationManager_ stopUpdatingLocation];
-}
-
-- (void)locationManager:(CLLocationManager*)manager
- didUpdateToLocation:(CLLocation*)newLocation
- fromLocation:(CLLocation*)oldLocation {
- Geoposition position;
- position.latitude = [newLocation coordinate].latitude;
- position.longitude = [newLocation coordinate].longitude;
- position.altitude = [newLocation altitude];
- position.accuracy = [newLocation horizontalAccuracy];
- position.altitude_accuracy = [newLocation verticalAccuracy];
- position.speed = [newLocation speed];
- position.heading = [newLocation course];
- position.timestamp = base::Time::Now();
- position.error_code = Geoposition::ERROR_CODE_NONE;
- dataProvider_->UpdatePosition(&position);
-}
-
-- (void)locationManager:(CLLocationManager*)manager
- didFailWithError:(NSError*)error {
- Geoposition position;
- switch ([error code]) {
- case kCLErrorLocationUnknown:
- position.error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
- break;
- case kCLErrorDenied:
- position.error_code = Geoposition::ERROR_CODE_PERMISSION_DENIED;
- break;
- default:
- NOTREACHED() << "Unknown CoreLocation error: " << [error code];
- return;
- }
- dataProvider_->UpdatePosition(&position);
-}
-
-- (BOOL)loadCoreLocationBundle {
- if (!bundle_) {
- bundle_ = [[NSBundle alloc]
- initWithPath:@"/System/Library/Frameworks/CoreLocation.framework"];
- if (!bundle_) {
- DLOG(WARNING) << "Couldn't load CoreLocation Framework";
- return NO;
- }
-
- locationManagerClass_ = [bundle_ classNamed:@"CLLocationManager"];
- }
-
- return YES;
-}
-
-@end
-
-namespace content {
-
-CoreLocationDataProviderMac::CoreLocationDataProviderMac() {
- if (base::MessageLoop::current() !=
- GeolocationProviderImpl::GetInstance()->message_loop()) {
- NOTREACHED() << "CoreLocation data provider must be created on "
- "the Geolocation thread.";
- }
- provider_ = NULL;
- wrapper_.reset([[CoreLocationWrapperMac alloc] initWithDataProvider:this]);
-}
-
-CoreLocationDataProviderMac::~CoreLocationDataProviderMac() {
-}
-
-// Returns true if the CoreLocation wrapper can load the framework and
-// location services are enabled. The pointer argument will only be accessed
-// in the origin thread.
-bool CoreLocationDataProviderMac::
- StartUpdating(CoreLocationProviderMac* provider) {
- DCHECK(provider);
- DCHECK(!provider_) << "StartUpdating called twice";
- if (![wrapper_ locationDataAvailable]) return false;
- provider_ = provider;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&CoreLocationDataProviderMac::StartUpdatingTask, this));
- return true;
-}
-
-// Clears provider_ so that any leftover messages from CoreLocation get ignored
-void CoreLocationDataProviderMac::StopUpdating() {
- provider_ = NULL;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&CoreLocationDataProviderMac::StopUpdatingTask, this));
-}
-
-void CoreLocationDataProviderMac::UpdatePosition(Geoposition *position) {
- GeolocationProviderImpl::GetInstance()->message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&CoreLocationDataProviderMac::PositionUpdated, this,
- *position));
-}
-
-// Runs in BrowserThread::UI
-void CoreLocationDataProviderMac::StartUpdatingTask() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- [wrapper_ startLocation];
-}
-
-// Runs in BrowserThread::UI
-void CoreLocationDataProviderMac::StopUpdatingTask() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- [wrapper_ stopLocation];
-}
-
-void CoreLocationDataProviderMac::PositionUpdated(Geoposition position) {
- DCHECK(base::MessageLoop::current() ==
- GeolocationProviderImpl::GetInstance()->message_loop());
- if (provider_)
- provider_->SetPosition(&position);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/geolocation/core_location_provider_mac.h b/chromium/content/browser/geolocation/core_location_provider_mac.h
deleted file mode 100644
index b4186d4ffb8..00000000000
--- a/chromium/content/browser/geolocation/core_location_provider_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.
-
-// This file declares a CoreLocation provider that runs on Mac OS X (10.6).
-// 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_CORE_LOCATION_PROVIDER_MAC_H_
-#define CONTENT_BROWSER_GEOLOCATION_CORE_LOCATION_PROVIDER_MAC_H_
-
-#include "content/browser/geolocation/location_provider_base.h"
-#include "content/public/common/geoposition.h"
-
-namespace content {
-class CoreLocationDataProviderMac;
-
-class CoreLocationProviderMac : public LocationProviderBase {
- public:
- explicit CoreLocationProviderMac();
- virtual ~CoreLocationProviderMac();
-
- // LocationProvider
- virtual bool StartProvider(bool high_accuracy) OVERRIDE;
- virtual void StopProvider() OVERRIDE;
- virtual void GetPosition(Geoposition* position) OVERRIDE;
- virtual void OnPermissionGranted() OVERRIDE;
-
- // Receives new positions and calls UpdateListeners
- void SetPosition(Geoposition* position);
-
- private:
- bool is_updating_;
- CoreLocationDataProviderMac* data_provider_;
- Geoposition position_;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_GEOLOCATION_CORE_LOCATION_PROVIDER_MAC_H_
diff --git a/chromium/content/browser/geolocation/core_location_provider_mac.mm b/chromium/content/browser/geolocation/core_location_provider_mac.mm
deleted file mode 100644
index 1c3aca1195c..00000000000
--- a/chromium/content/browser/geolocation/core_location_provider_mac.mm
+++ /dev/null
@@ -1,68 +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/core_location_provider_mac.h"
-
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "content/browser/geolocation/core_location_data_provider_mac.h"
-#include "content/public/common/content_switches.h"
-
-namespace content {
-
-CoreLocationProviderMac::CoreLocationProviderMac()
- : is_updating_(false) {
- data_provider_ = new CoreLocationDataProviderMac();
- data_provider_->AddRef();
-}
-
-CoreLocationProviderMac::~CoreLocationProviderMac() {
- data_provider_->StopUpdating();
- data_provider_->Release();
-}
-
-bool CoreLocationProviderMac::StartProvider(bool high_accuracy) {
- // StartProvider maybe called multiple times. For example, to update the high
- // accuracy hint.
- // TODO(jknotten): Support high_accuracy hint in underlying data provider.
- if (is_updating_)
- return true;
-
- is_updating_ = data_provider_->StartUpdating(this);
- return true;
-}
-
-void CoreLocationProviderMac::StopProvider() {
- data_provider_->StopUpdating();
- is_updating_ = false;
-}
-
-void CoreLocationProviderMac::GetPosition(Geoposition* position) {
- DCHECK(position);
- *position = position_;
- DCHECK(position->Validate() ||
- position->error_code != Geoposition::ERROR_CODE_NONE);
-}
-
-void CoreLocationProviderMac::OnPermissionGranted() {
-}
-
-void CoreLocationProviderMac::SetPosition(Geoposition* position) {
- DCHECK(position);
- position_ = *position;
- DCHECK(position->Validate() ||
- position->error_code != Geoposition::ERROR_CODE_NONE);
-
- NotifyCallback(position_);
-}
-
-LocationProvider* NewSystemLocationProvider() {
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kExperimentalLocationFeatures)) {
- return new CoreLocationProviderMac;
- }
- return NULL;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/geolocation/device_data_provider.h b/chromium/content/browser/geolocation/device_data_provider.h
deleted file mode 100644
index d8907354a23..00000000000
--- a/chromium/content/browser/geolocation/device_data_provider.h
+++ /dev/null
@@ -1,305 +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.
-
-// A device data provider provides data from the device that is used by a
-// NetworkLocationProvider to obtain a position fix. This data may be either
-// cell radio data or wifi data. For a given type of data, we use a singleton
-// instance of the device data provider, which is used by multiple
-// NetworkLocationProvider objects.
-//
-// This file providers DeviceDataProvider, which provides static methods to
-// access the singleton instance. The singleton instance uses a private
-// implementation to abstract across platforms and also to allow mock providers
-// to be used for testing.
-//
-// This file also provides DeviceDataProviderImplBase, a base class which
-// provides commom functionality for the private implementations.
-//
-// This file also declares the data structures used to represent cell radio data
-// and wifi data.
-
-#ifndef CONTENT_BROWSER_GEOLOCATION_DEVICE_DATA_PROVIDER_H_
-#define CONTENT_BROWSER_GEOLOCATION_DEVICE_DATA_PROVIDER_H_
-
-#include <set>
-
-#include "base/basictypes.h"
-#include "base/bind.h"
-#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_util.h"
-#include "base/threading/non_thread_safe.h"
-#include "content/common/content_export.h"
-
-namespace content {
-
-// Wifi data relating to a single access point.
-struct CONTENT_EXPORT AccessPointData {
- AccessPointData();
- ~AccessPointData();
-
- // MAC address, formatted as per MacAddressAsString16.
- string16 mac_address;
- int radio_signal_strength; // Measured in dBm
- int channel;
- int signal_to_noise; // Ratio in dB
- string16 ssid; // Network identifier
-};
-
-// This is to allow AccessPointData to be used in std::set. We order
-// lexicographically by MAC address.
-struct AccessPointDataLess {
- bool operator()(const AccessPointData& data1,
- const AccessPointData& data2) const {
- return data1.mac_address < data2.mac_address;
- }
-};
-
-// All data for wifi.
-struct CONTENT_EXPORT WifiData {
- WifiData();
- ~WifiData();
-
- // Determines whether a new set of WiFi data differs significantly from this.
- bool DiffersSignificantly(const WifiData& other) const;
-
- // Store access points as a set, sorted by MAC address. This allows quick
- // comparison of sets for detecting changes and for caching.
- typedef std::set<AccessPointData, AccessPointDataLess> AccessPointDataSet;
- AccessPointDataSet access_point_data;
-};
-
-template<typename DataType>
-class DeviceDataProvider;
-
-// This class just exists to work-around MSVC2005 not being able to have a
-// template class implement RefCountedThreadSafe
-class CONTENT_EXPORT DeviceDataProviderImplBaseHack
- : public base::RefCountedThreadSafe<DeviceDataProviderImplBaseHack> {
- protected:
- friend class base::RefCountedThreadSafe<DeviceDataProviderImplBaseHack>;
- virtual ~DeviceDataProviderImplBaseHack() {}
-};
-
-// See class DeviceDataProvider for the public client API.
-// DeviceDataProvider uses containment to hide platform-specific implementation
-// details from common code. This class provides common functionality for these
-// contained implementation classes. This is a modified pimpl pattern: this
-// class needs to be in the public header due to use of templating.
-template<typename DataType>
-class DeviceDataProviderImplBase : public DeviceDataProviderImplBaseHack {
- public:
- DeviceDataProviderImplBase()
- : container_(NULL), client_loop_(base::MessageLoop::current()) {
- DCHECK(client_loop_);
- }
-
- virtual bool StartDataProvider() = 0;
- virtual void StopDataProvider() = 0;
- virtual bool GetData(DataType* data) = 0;
-
- // Sets the container of this class, which is of type DeviceDataProvider.
- // This is required to pass as a parameter when making the callback to
- // listeners.
- void SetContainer(DeviceDataProvider<DataType>* container) {
- DCHECK(CalledOnClientThread());
- container_ = container;
- }
-
- typedef typename DeviceDataProvider<DataType>::ListenerInterface
- ListenerInterface;
- void AddListener(ListenerInterface* listener) {
- DCHECK(CalledOnClientThread());
- listeners_.insert(listener);
- }
- bool RemoveListener(ListenerInterface* listener) {
- DCHECK(CalledOnClientThread());
- return listeners_.erase(listener) == 1;
- }
-
- bool has_listeners() const {
- DCHECK(CalledOnClientThread());
- return !listeners_.empty();
- }
-
- protected:
- virtual ~DeviceDataProviderImplBase() {}
-
- // Calls DeviceDataUpdateAvailable() on all registered listeners.
- typedef std::set<ListenerInterface*> ListenersSet;
- void NotifyListeners() {
- // Always make the notify callback via a posted task, so we can unwind
- // callstack here and make callback without causing client re-entrancy.
- client_loop_->PostTask(FROM_HERE, base::Bind(
- &DeviceDataProviderImplBase<DataType>::NotifyListenersInClientLoop,
- this));
- }
-
- bool CalledOnClientThread() const {
- return base::MessageLoop::current() == this->client_loop_;
- }
-
- base::MessageLoop* client_loop() const { return client_loop_; }
-
- private:
- void NotifyListenersInClientLoop() {
- DCHECK(CalledOnClientThread());
- // It's possible that all the listeners (and the container) went away
- // whilst this task was pending. This is fine; the loop will be a no-op.
- typename ListenersSet::const_iterator iter = listeners_.begin();
- while (iter != listeners_.end()) {
- ListenerInterface* listener = *iter;
- ++iter; // Advance iter before callback, in case listener unregisters.
- listener->DeviceDataUpdateAvailable(container_);
- }
- }
-
- DeviceDataProvider<DataType>* container_;
-
- // Reference to the client's message loop, all callbacks and access to
- // the listeners_ member should happen in this context.
- base::MessageLoop* client_loop_;
-
- ListenersSet listeners_;
-
- DISALLOW_COPY_AND_ASSIGN(DeviceDataProviderImplBase);
-};
-
-typedef DeviceDataProviderImplBase<WifiData> WifiDataProviderImplBase;
-
-// A device data provider
-//
-// We use a singleton instance of this class which is shared by multiple network
-// location providers. These location providers access the instance through the
-// Register and Unregister methods.
-template<typename DataType>
-class DeviceDataProvider : public base::NonThreadSafe {
- public:
- // Interface to be implemented by listeners to a device data provider.
- class ListenerInterface {
- public:
- // Will be called in the context of the thread that called Register().
- virtual void DeviceDataUpdateAvailable(
- DeviceDataProvider<DataType>* provider) = 0;
- virtual ~ListenerInterface() {}
- };
-
- // Sets the factory function which will be used by Register to create the
- // implementation used by the singleton instance. This factory approach is
- // used to abastract accross both platform-specific implementation and to
- // inject mock implementations for testing.
- typedef DeviceDataProviderImplBase<DataType>* (*ImplFactoryFunction)(void);
- static void SetFactory(ImplFactoryFunction factory_function_in) {
- factory_function_ = factory_function_in;
- }
-
- static void ResetFactory() {
- factory_function_ = DefaultFactoryFunction;
- }
-
- // Adds a listener, which will be called back with DeviceDataUpdateAvailable
- // whenever new data is available. Returns the singleton instance.
- static DeviceDataProvider* Register(ListenerInterface* listener) {
- bool need_to_start_thread = false;
- if (!instance_) {
- instance_ = new DeviceDataProvider();
- need_to_start_thread = true;
- }
- DCHECK(instance_);
- DCHECK(instance_->CalledOnValidThread());
- instance_->AddListener(listener);
- // Start the provider after adding the listener, to avoid any race in
- // it receiving an early callback.
- if (need_to_start_thread) {
- bool started = instance_->StartDataProvider();
- DCHECK(started);
- }
- return instance_;
- }
-
- // Removes a listener. If this is the last listener, deletes the singleton
- // instance. Return value indicates success.
- static bool Unregister(ListenerInterface* listener) {
- DCHECK(instance_);
- DCHECK(instance_->CalledOnValidThread());
- DCHECK(instance_->has_listeners());
- if (!instance_->RemoveListener(listener)) {
- return false;
- }
- if (!instance_->has_listeners()) {
- // Must stop the provider (and any implementation threads) before
- // destroying to avoid any race conditions in access to the provider in
- // the destructor chain.
- instance_->StopDataProvider();
- delete instance_;
- instance_ = NULL;
- }
- return true;
- }
-
- // Provides whatever data the provider has, which may be nothing. Return
- // value indicates whether this is all the data the provider could ever
- // obtain.
- bool GetData(DataType* data) {
- DCHECK(this->CalledOnValidThread());
- return impl_->GetData(data);
- }
-
- private:
- // Private constructor and destructor, callers access singleton through
- // Register and Unregister.
- DeviceDataProvider() {
- DCHECK(factory_function_);
- impl_ = (*factory_function_)();
- DCHECK(impl_.get());
- impl_->SetContainer(this);
- }
- virtual ~DeviceDataProvider() {
- DCHECK(impl_.get());
- impl_->SetContainer(NULL);
- }
-
- void AddListener(ListenerInterface* listener) {
- impl_->AddListener(listener);
- }
-
- bool RemoveListener(ListenerInterface* listener) {
- return impl_->RemoveListener(listener);
- }
-
- bool has_listeners() const {
- return impl_->has_listeners();
- }
-
- bool StartDataProvider() {
- return impl_->StartDataProvider();
- }
-
- void StopDataProvider() {
- impl_->StopDataProvider();
- }
-
- CONTENT_EXPORT static DeviceDataProviderImplBase<DataType>*
- DefaultFactoryFunction();
-
- // The singleton-like instance of this class. (Not 'true' singleton, as it
- // may go through multiple create/destroy/create cycles per process instance,
- // e.g. when under test).
- CONTENT_EXPORT static DeviceDataProvider* instance_;
-
- // The factory function used to create the singleton instance.
- CONTENT_EXPORT static ImplFactoryFunction factory_function_;
-
- // The internal implementation.
- scoped_refptr<DeviceDataProviderImplBase<DataType> > impl_;
-
- DISALLOW_COPY_AND_ASSIGN(DeviceDataProvider);
-};
-
-typedef DeviceDataProvider<WifiData> WifiDataProvider;
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_GEOLOCATION_DEVICE_DATA_PROVIDER_H_
diff --git a/chromium/content/browser/geolocation/device_data_provider_unittest.cc b/chromium/content/browser/geolocation/device_data_provider_unittest.cc
deleted file mode 100644
index 42a678c8d5e..00000000000
--- a/chromium/content/browser/geolocation/device_data_provider_unittest.cc
+++ /dev/null
@@ -1,41 +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/threading/platform_thread.h"
-#include "content/browser/geolocation/device_data_provider.h"
-#include "content/browser/geolocation/wifi_data_provider_common.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-class NullWifiDataListenerInterface
- : public WifiDataProviderCommon::ListenerInterface {
- public:
- // ListenerInterface
- virtual void DeviceDataUpdateAvailable(
- DeviceDataProvider<WifiData>* provider) OVERRIDE {}
-};
-
-TEST(GeolocationDeviceDataProviderWifiData, CreateDestroy) {
- // See http://crbug.com/59913 . The main_message_loop is not required to be
- // run for correct behaviour, but we run it in this test to help smoke out
- // any race conditions between processing in the main loop and the setup /
- // tear down of the DeviceDataProvider thread.
- base::MessageLoopForUI main_message_loop;
- NullWifiDataListenerInterface listener;
- for (int i = 0; i < 10; i++) {
- DeviceDataProvider<WifiData>::Register(&listener);
- for (int j = 0; j < 10; j++) {
- base::PlatformThread::Sleep(base::TimeDelta());
- main_message_loop.RunUntilIdle(); // See comment above
- }
- DeviceDataProvider<WifiData>::Unregister(&listener);
- for (int j = 0; j < 10; j++) {
- base::PlatformThread::Sleep(base::TimeDelta());
- main_message_loop.RunUntilIdle(); // See comment above
- }
- }
-}
-
-} // namespace content
diff --git a/chromium/content/browser/geolocation/empty_device_data_provider.cc b/chromium/content/browser/geolocation/empty_device_data_provider.cc
deleted file mode 100644
index 57e25b0a504..00000000000
--- a/chromium/content/browser/geolocation/empty_device_data_provider.cc
+++ /dev/null
@@ -1,18 +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/empty_device_data_provider.h"
-
-namespace content {
-
-// Only define for platforms that lack a real wifi data provider.
-#if !defined(OS_WIN) && !defined(OS_MACOSX) && !defined(OS_LINUX)
-// static
-template<>
-WifiDataProviderImplBase* WifiDataProvider::DefaultFactoryFunction() {
- return new EmptyDeviceDataProvider<WifiData>();
-}
-#endif
-
-} // namespace content
diff --git a/chromium/content/browser/geolocation/empty_device_data_provider.h b/chromium/content/browser/geolocation/empty_device_data_provider.h
deleted file mode 100644
index 76653f55cfe..00000000000
--- a/chromium/content/browser/geolocation/empty_device_data_provider.h
+++ /dev/null
@@ -1,36 +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_GEOLOCATION_EMPTY_DEVICE_DATA_PROVIDER_H_
-#define CONTENT_BROWSER_GEOLOCATION_EMPTY_DEVICE_DATA_PROVIDER_H_
-
-#include "content/browser/geolocation/device_data_provider.h"
-
-namespace content {
-
-// An implementation of DeviceDataProviderImplBase that does not provide any
-// data. Used on platforms where a given data type is not available.
-
-template<typename DataType>
-class EmptyDeviceDataProvider : public DeviceDataProviderImplBase<DataType> {
- public:
- EmptyDeviceDataProvider() {}
- virtual ~EmptyDeviceDataProvider() {}
-
- // DeviceDataProviderImplBase implementation
- virtual bool StartDataProvider() { return true; }
- virtual void StopDataProvider() { }
- virtual bool GetData(DataType *data) {
- DCHECK(data);
- // This is all the data we can get - nothing.
- return true;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(EmptyDeviceDataProvider);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_GEOLOCATION_EMPTY_DEVICE_DATA_PROVIDER_H_
diff --git a/chromium/content/browser/geolocation/empty_wifi_data_provider.cc b/chromium/content/browser/geolocation/empty_wifi_data_provider.cc
new file mode 100644
index 00000000000..7255f46fcc9
--- /dev/null
+++ b/chromium/content/browser/geolocation/empty_wifi_data_provider.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/browser/geolocation/empty_wifi_data_provider.h"
+
+namespace content {
+
+EmptyWifiDataProvider::EmptyWifiDataProvider() {
+}
+
+EmptyWifiDataProvider::~EmptyWifiDataProvider() {
+}
+
+bool EmptyWifiDataProvider::GetData(WifiData* data) {
+ DCHECK(data);
+ // This is all the data we can get - nothing.
+ 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/empty_wifi_data_provider.h b/chromium/content/browser/geolocation/empty_wifi_data_provider.h
new file mode 100644
index 00000000000..a02ed2bc9b7
--- /dev/null
+++ b/chromium/content/browser/geolocation/empty_wifi_data_provider.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_BROWSER_GEOLOCATION_EMPTY_WIFI_DATA_PROVIDER_H_
+#define CONTENT_BROWSER_GEOLOCATION_EMPTY_WIFI_DATA_PROVIDER_H_
+
+#include "content/browser/geolocation/wifi_data_provider.h"
+
+namespace content {
+
+// An implementation of WifiDataProviderImplBase that does not provide any
+// data. Used on platforms where a real implementation is not available.
+class EmptyWifiDataProvider : public WifiDataProviderImplBase {
+ public:
+ EmptyWifiDataProvider();
+
+ // WifiDataProviderImplBase implementation
+ virtual void StartDataProvider() OVERRIDE { }
+ virtual void StopDataProvider() OVERRIDE { }
+ virtual bool GetData(WifiData* data) OVERRIDE;
+
+ private:
+ virtual ~EmptyWifiDataProvider();
+
+ DISALLOW_COPY_AND_ASSIGN(EmptyWifiDataProvider);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GEOLOCATION_EMPTY_WIFI_DATA_PROVIDER_H_
diff --git a/chromium/content/browser/geolocation/geolocation_dispatcher_host.cc b/chromium/content/browser/geolocation/geolocation_dispatcher_host.cc
index 53f8e4feafb..38f77504cfb 100644
--- a/chromium/content/browser/geolocation/geolocation_dispatcher_host.cc
+++ b/chromium/content/browser/geolocation/geolocation_dispatcher_host.cc
@@ -20,7 +20,7 @@
namespace content {
namespace {
-void NotifyArbitratorPermissionGranted() {
+void NotifyGeolocationProviderPermissionGranted() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
GeolocationProviderImpl::GetInstance()->UserDidOptIntoLocationServices();
}
@@ -30,16 +30,17 @@ void SendGeolocationPermissionResponse(int render_process_id,
int bridge_id,
bool allowed) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- RenderViewHostImpl* r =
+ RenderViewHostImpl* render_view_host =
RenderViewHostImpl::FromID(render_process_id, render_view_id);
- if (!r)
+ if (!render_view_host)
return;
- r->Send(new GeolocationMsg_PermissionSet(render_view_id, bridge_id, allowed));
+ render_view_host->Send(
+ new GeolocationMsg_PermissionSet(render_view_id, bridge_id, allowed));
if (allowed) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&NotifyArbitratorPermissionGranted));
+ base::Bind(&NotifyGeolocationProviderPermissionGranted));
}
}
@@ -67,7 +68,7 @@ class GeolocationDispatcherHostImpl : public GeolocationDispatcherHost {
bool enable_high_accuracy);
void OnStopUpdating(int render_view_id);
- // Updates the |location_arbitrator_| with the currently required update
+ // Updates the |geolocation_provider_| with the currently required update
// options, based on |renderer_high_accuracy_|.
void RefreshHighAccuracy();
@@ -81,11 +82,11 @@ class GeolocationDispatcherHostImpl : public GeolocationDispatcherHost {
// context switches.
// Only used on the IO thread.
std::set<int> geolocation_renderer_ids_;
- // Maps renderer_id to whether high accuracy is requestd for this particular
+ // Maps renderer_id to whether high accuracy is requested for this particular
// bridge.
std::map<int, bool> renderer_high_accuracy_;
- // Only set whilst we are registered with the arbitrator.
- GeolocationProviderImpl* location_provider_;
+ // Only set whilst we are registered with the geolocation provider.
+ GeolocationProviderImpl* geolocation_provider_;
GeolocationProviderImpl::LocationUpdateCallback callback_;
@@ -97,7 +98,7 @@ GeolocationDispatcherHostImpl::GeolocationDispatcherHostImpl(
GeolocationPermissionContext* geolocation_permission_context)
: render_process_id_(render_process_id),
geolocation_permission_context_(geolocation_permission_context),
- location_provider_(NULL) {
+ geolocation_provider_(NULL) {
callback_ = base::Bind(
&GeolocationDispatcherHostImpl::OnLocationUpdate, base::Unretained(this));
// This is initialized by ResourceMessageFilter. Do not add any non-trivial
@@ -106,8 +107,8 @@ GeolocationDispatcherHostImpl::GeolocationDispatcherHostImpl(
}
GeolocationDispatcherHostImpl::~GeolocationDispatcherHostImpl() {
- if (location_provider_)
- location_provider_->RemoveLocationUpdateCallback(callback_);
+ if (geolocation_provider_)
+ geolocation_provider_->RemoveLocationUpdateCallback(callback_);
}
bool GeolocationDispatcherHostImpl::OnMessageReceived(
@@ -204,13 +205,13 @@ void GeolocationDispatcherHostImpl::OnStopUpdating(int render_view_id) {
void GeolocationDispatcherHostImpl::RefreshHighAccuracy() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (renderer_high_accuracy_.empty()) {
- if (location_provider_) {
- location_provider_->RemoveLocationUpdateCallback(callback_);
- location_provider_ = NULL;
+ if (geolocation_provider_) {
+ geolocation_provider_->RemoveLocationUpdateCallback(callback_);
+ geolocation_provider_ = NULL;
}
} else {
- if (!location_provider_)
- location_provider_ = GeolocationProviderImpl::GetInstance();
+ 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();
@@ -220,7 +221,8 @@ void GeolocationDispatcherHostImpl::RefreshHighAccuracy() {
break;
}
}
- location_provider_->AddLocationUpdateCallback(callback_, use_high_accuracy);
+ geolocation_provider_->AddLocationUpdateCallback(
+ callback_, use_high_accuracy);
}
}
} // namespace
diff --git a/chromium/content/browser/geolocation/geolocation_provider_impl.cc b/chromium/content/browser/geolocation/geolocation_provider_impl.cc
index f24cb2dcb7a..f343c2920ff 100644
--- a/chromium/content/browser/geolocation/geolocation_provider_impl.cc
+++ b/chromium/content/browser/geolocation/geolocation_provider_impl.cc
@@ -227,10 +227,10 @@ void GeolocationProviderImpl::CleanUp() {
arbitrator_ = NULL;
}
-GeolocationArbitrator* GeolocationProviderImpl::CreateArbitrator() {
- GeolocationArbitratorImpl::LocationUpdateCallback callback = base::Bind(
+LocationArbitrator* GeolocationProviderImpl::CreateArbitrator() {
+ LocationArbitratorImpl::LocationUpdateCallback callback = base::Bind(
&GeolocationProviderImpl::OnLocationUpdate, base::Unretained(this));
- return new GeolocationArbitratorImpl(callback);
+ return new LocationArbitratorImpl(callback);
}
} // namespace content
diff --git a/chromium/content/browser/geolocation/geolocation_provider_impl.h b/chromium/content/browser/geolocation/geolocation_provider_impl.h
index d4b5afb1074..6613f44fc69 100644
--- a/chromium/content/browser/geolocation/geolocation_provider_impl.h
+++ b/chromium/content/browser/geolocation/geolocation_provider_impl.h
@@ -19,17 +19,13 @@
template<typename Type> struct DefaultSingletonTraits;
namespace content {
-class GeolocationArbitrator;
-class GeolocationProviderTest;
+class LocationArbitrator;
// This is the main API to the geolocation subsystem. The application will hold
// a single instance of this class and can register multiple clients to be
// notified of location changes:
-// * Observers are registered by AddLocationUpdateCallback() and will keep
-// receiving updates
-// until unregistered by RemoveLocationUpdateCallback().
-// * Callbacks are registered by RequestCallback() and will be called exactly
-// once when the next update becomes available.
+// * Callbacks are registered by AddLocationUpdateCallback() and will keep
+// receiving updates until unregistered by RemoveLocationUpdateCallback().
// The application must instantiate the GeolocationProvider on the IO thread and
// must communicate with it on the same thread.
// The underlying location arbitrator will only be enabled whilst there is at
@@ -53,7 +49,7 @@ class CONTENT_EXPORT GeolocationProviderImpl
// position to all registered clients.
void OverrideLocationForTesting(const Geoposition& override_position);
- // Callback from the GeolocationArbitrator. Public for testing.
+ // Callback from the LocationArbitrator. Public for testing.
void OnLocationUpdate(const Geoposition& position);
// Gets a pointer to the singleton instance of the location relayer, which
@@ -68,7 +64,7 @@ class CONTENT_EXPORT GeolocationProviderImpl
virtual ~GeolocationProviderImpl();
// Useful for injecting mock geolocation arbitrator in tests.
- virtual GeolocationArbitrator* CreateArbitrator();
+ virtual LocationArbitrator* CreateArbitrator();
private:
typedef std::pair<LocationUpdateCallback, bool> LocationUpdateInfo;
@@ -107,7 +103,7 @@ class CONTENT_EXPORT GeolocationProviderImpl
bool ignore_location_updates_;
// Only to be used on the geolocation thread.
- GeolocationArbitrator* arbitrator_;
+ LocationArbitrator* arbitrator_;
DISALLOW_COPY_AND_ASSIGN(GeolocationProviderImpl);
};
diff --git a/chromium/content/browser/geolocation/geolocation_provider_unittest.cc b/chromium/content/browser/geolocation/geolocation_provider_unittest.cc
index 47b397a9a90..a2aa88d9e65 100644
--- a/chromium/content/browser/geolocation/geolocation_provider_unittest.cc
+++ b/chromium/content/browser/geolocation/geolocation_provider_unittest.cc
@@ -30,21 +30,21 @@ class LocationProviderForTestArbitrator : public GeolocationProviderImpl {
virtual ~LocationProviderForTestArbitrator() {}
// Only valid for use on the geolocation thread.
- MockGeolocationArbitrator* mock_arbitrator() const {
+ MockLocationArbitrator* mock_arbitrator() const {
return mock_arbitrator_;
}
protected:
// GeolocationProviderImpl implementation:
- virtual GeolocationArbitrator* CreateArbitrator() OVERRIDE;
+ virtual LocationArbitrator* CreateArbitrator() OVERRIDE;
private:
- MockGeolocationArbitrator* mock_arbitrator_;
+ MockLocationArbitrator* mock_arbitrator_;
};
-GeolocationArbitrator* LocationProviderForTestArbitrator::CreateArbitrator() {
+LocationArbitrator* LocationProviderForTestArbitrator::CreateArbitrator() {
DCHECK(mock_arbitrator_ == NULL);
- mock_arbitrator_ = new MockGeolocationArbitrator;
+ mock_arbitrator_ = new MockLocationArbitrator;
return mock_arbitrator_;
}
diff --git a/chromium/content/browser/geolocation/location_arbitrator.h b/chromium/content/browser/geolocation/location_arbitrator.h
index 4bf82b03ac5..d2cd191c798 100644
--- a/chromium/content/browser/geolocation/location_arbitrator.h
+++ b/chromium/content/browser/geolocation/location_arbitrator.h
@@ -12,9 +12,9 @@ namespace content {
// This class is responsible for handling updates from multiple underlying
// providers and resolving them to a single 'best' location fix at any given
// moment.
-class CONTENT_EXPORT GeolocationArbitrator {
+class CONTENT_EXPORT LocationArbitrator {
public:
- virtual ~GeolocationArbitrator() {};
+ virtual ~LocationArbitrator() {};
// See more details in geolocation_provider.
virtual void StartProviders(bool use_high_accuracy) = 0;
diff --git a/chromium/content/browser/geolocation/location_arbitrator_impl.cc b/chromium/content/browser/geolocation/location_arbitrator_impl.cc
index 49c1c10b85e..149eb133b8e 100644
--- a/chromium/content/browser/geolocation/location_arbitrator_impl.cc
+++ b/chromium/content/browser/geolocation/location_arbitrator_impl.cc
@@ -23,28 +23,28 @@ const char* kDefaultNetworkProviderUrl =
// To avoid oscillations, set this to twice the expected update interval of a
// a GPS-type location provider (in case it misses a beat) plus a little.
-const int64 GeolocationArbitratorImpl::kFixStaleTimeoutMilliseconds =
+const int64 LocationArbitratorImpl::kFixStaleTimeoutMilliseconds =
11 * base::Time::kMillisecondsPerSecond;
-GeolocationArbitratorImpl::GeolocationArbitratorImpl(
+LocationArbitratorImpl::LocationArbitratorImpl(
const LocationUpdateCallback& callback)
: callback_(callback),
provider_callback_(
- base::Bind(&GeolocationArbitratorImpl::LocationUpdateAvailable,
+ base::Bind(&LocationArbitratorImpl::LocationUpdateAvailable,
base::Unretained(this))),
position_provider_(NULL),
is_permission_granted_(false),
is_running_(false) {
}
-GeolocationArbitratorImpl::~GeolocationArbitratorImpl() {
+LocationArbitratorImpl::~LocationArbitratorImpl() {
}
-GURL GeolocationArbitratorImpl::DefaultNetworkProviderURL() {
+GURL LocationArbitratorImpl::DefaultNetworkProviderURL() {
return GURL(kDefaultNetworkProviderUrl);
}
-void GeolocationArbitratorImpl::OnPermissionGranted() {
+void LocationArbitratorImpl::OnPermissionGranted() {
is_permission_granted_ = true;
for (ScopedVector<LocationProvider>::iterator i = providers_.begin();
i != providers_.end(); ++i) {
@@ -52,28 +52,28 @@ void GeolocationArbitratorImpl::OnPermissionGranted() {
}
}
-void GeolocationArbitratorImpl::StartProviders(bool use_high_accuracy) {
+void LocationArbitratorImpl::StartProviders(bool use_high_accuracy) {
// Stash options as OnAccessTokenStoresLoaded has not yet been called.
is_running_ = true;
use_high_accuracy_ = use_high_accuracy;
if (providers_.empty()) {
DCHECK(DefaultNetworkProviderURL().is_valid());
GetAccessTokenStore()->LoadAccessTokens(
- base::Bind(&GeolocationArbitratorImpl::OnAccessTokenStoresLoaded,
+ base::Bind(&LocationArbitratorImpl::OnAccessTokenStoresLoaded,
base::Unretained(this)));
} else {
DoStartProviders();
}
}
-void GeolocationArbitratorImpl::DoStartProviders() {
+void LocationArbitratorImpl::DoStartProviders() {
for (ScopedVector<LocationProvider>::iterator i = providers_.begin();
i != providers_.end(); ++i) {
(*i)->StartProvider(use_high_accuracy_);
}
}
-void GeolocationArbitratorImpl::StopProviders() {
+void LocationArbitratorImpl::StopProviders() {
// Reset the reference location state (provider+position)
// so that future starts use fresh locations from
// the newly constructed providers.
@@ -84,7 +84,7 @@ void GeolocationArbitratorImpl::StopProviders() {
is_running_ = false;
}
-void GeolocationArbitratorImpl::OnAccessTokenStoresLoaded(
+void LocationArbitratorImpl::OnAccessTokenStoresLoaded(
AccessTokenStore::AccessTokenSet access_token_set,
net::URLRequestContextGetter* context_getter) {
if (!is_running_ || !providers_.empty()) {
@@ -112,7 +112,7 @@ void GeolocationArbitratorImpl::OnAccessTokenStoresLoaded(
DoStartProviders();
}
-void GeolocationArbitratorImpl::RegisterProvider(
+void LocationArbitratorImpl::RegisterProvider(
LocationProvider* provider) {
if (!provider)
return;
@@ -122,7 +122,7 @@ void GeolocationArbitratorImpl::RegisterProvider(
providers_.push_back(provider);
}
-void GeolocationArbitratorImpl::LocationUpdateAvailable(
+void LocationArbitratorImpl::LocationUpdateAvailable(
const LocationProvider* provider,
const Geoposition& new_position) {
DCHECK(new_position.Validate() ||
@@ -135,17 +135,17 @@ void GeolocationArbitratorImpl::LocationUpdateAvailable(
callback_.Run(position_);
}
-AccessTokenStore* GeolocationArbitratorImpl::NewAccessTokenStore() {
+AccessTokenStore* LocationArbitratorImpl::NewAccessTokenStore() {
return GetContentClient()->browser()->CreateAccessTokenStore();
}
-AccessTokenStore* GeolocationArbitratorImpl::GetAccessTokenStore() {
+AccessTokenStore* LocationArbitratorImpl::GetAccessTokenStore() {
if (!access_token_store_.get())
access_token_store_ = NewAccessTokenStore();
return access_token_store_.get();
}
-LocationProvider* GeolocationArbitratorImpl::NewNetworkLocationProvider(
+LocationProvider* LocationArbitratorImpl::NewNetworkLocationProvider(
AccessTokenStore* access_token_store,
net::URLRequestContextGetter* context,
const GURL& url,
@@ -159,19 +159,19 @@ LocationProvider* GeolocationArbitratorImpl::NewNetworkLocationProvider(
#endif
}
-LocationProvider* GeolocationArbitratorImpl::NewSystemLocationProvider() {
-#if defined(OS_WIN)
+LocationProvider* LocationArbitratorImpl::NewSystemLocationProvider() {
+#if defined(OS_WIN) || defined(OS_MACOSX)
return NULL;
#else
return content::NewSystemLocationProvider();
#endif
}
-base::Time GeolocationArbitratorImpl::GetTimeNow() const {
+base::Time LocationArbitratorImpl::GetTimeNow() const {
return base::Time::Now();
}
-bool GeolocationArbitratorImpl::IsNewPositionBetter(
+bool LocationArbitratorImpl::IsNewPositionBetter(
const Geoposition& old_position, const Geoposition& new_position,
bool from_same_provider) const {
// Updates location_info if it's better than what we currently have,
@@ -197,7 +197,7 @@ bool GeolocationArbitratorImpl::IsNewPositionBetter(
return false;
}
-bool GeolocationArbitratorImpl::HasPermissionBeenGranted() const {
+bool LocationArbitratorImpl::HasPermissionBeenGranted() const {
return is_permission_granted_;
}
diff --git a/chromium/content/browser/geolocation/location_arbitrator_impl.h b/chromium/content/browser/geolocation/location_arbitrator_impl.h
index 91ffa0c356f..45910552e4e 100644
--- a/chromium/content/browser/geolocation/location_arbitrator_impl.h
+++ b/chromium/content/browser/geolocation/location_arbitrator_impl.h
@@ -27,8 +27,7 @@ class LocationProvider;
// This class is responsible for handling updates from multiple underlying
// providers and resolving them to a single 'best' location fix at any given
// moment.
-class CONTENT_EXPORT GeolocationArbitratorImpl
- : public GeolocationArbitrator {
+class CONTENT_EXPORT LocationArbitratorImpl : public LocationArbitrator {
public:
// Number of milliseconds newer a location provider has to be that it's worth
// switching to this location provider on the basis of it being fresher
@@ -37,12 +36,12 @@ class CONTENT_EXPORT GeolocationArbitratorImpl
typedef base::Callback<void(const Geoposition&)> LocationUpdateCallback;
- explicit GeolocationArbitratorImpl(const LocationUpdateCallback& callback);
- virtual ~GeolocationArbitratorImpl();
+ explicit LocationArbitratorImpl(const LocationUpdateCallback& callback);
+ virtual ~LocationArbitratorImpl();
static GURL DefaultNetworkProviderURL();
- // GeolocationArbitrator
+ // LocationArbitrator
virtual void StartProviders(bool use_high_accuracy) OVERRIDE;
virtual void StopProviders() OVERRIDE;
virtual void OnPermissionGranted() OVERRIDE;
@@ -96,7 +95,7 @@ class CONTENT_EXPORT GeolocationArbitratorImpl
// Tracks whether providers should be running.
bool is_running_;
- DISALLOW_COPY_AND_ASSIGN(GeolocationArbitratorImpl);
+ DISALLOW_COPY_AND_ASSIGN(LocationArbitratorImpl);
};
// Factory functions for the various types of location provider to abstract
diff --git a/chromium/content/browser/geolocation/location_arbitrator_impl_unittest.cc b/chromium/content/browser/geolocation/location_arbitrator_impl_unittest.cc
index ce2d1e27ad0..02df43172ee 100644
--- a/chromium/content/browser/geolocation/location_arbitrator_impl_unittest.cc
+++ b/chromium/content/browser/geolocation/location_arbitrator_impl_unittest.cc
@@ -62,12 +62,12 @@ void SetReferencePosition(MockLocationProvider* provider) {
namespace {
-class TestingGeolocationArbitrator : public GeolocationArbitratorImpl {
+class TestingLocationArbitrator : public LocationArbitratorImpl {
public:
- TestingGeolocationArbitrator(
- const GeolocationArbitratorImpl::LocationUpdateCallback& callback,
+ TestingLocationArbitrator(
+ const LocationArbitratorImpl::LocationUpdateCallback& callback,
AccessTokenStore* access_token_store)
- : GeolocationArbitratorImpl(callback),
+ : LocationArbitratorImpl(callback),
cell_(NULL),
gps_(NULL),
access_token_store_(access_token_store) {
@@ -110,10 +110,10 @@ class GeolocationLocationArbitratorTest : public testing::Test {
virtual void SetUp() {
access_token_store_ = new NiceMock<FakeAccessTokenStore>;
observer_.reset(new MockLocationObserver);
- GeolocationArbitratorImpl::LocationUpdateCallback callback =
+ LocationArbitratorImpl::LocationUpdateCallback callback =
base::Bind(&MockLocationObserver::OnLocationUpdate,
base::Unretained(observer_.get()));
- arbitrator_.reset(new TestingGeolocationArbitrator(
+ arbitrator_.reset(new TestingLocationArbitrator(
callback, access_token_store_.get()));
}
@@ -134,7 +134,7 @@ class GeolocationLocationArbitratorTest : public testing::Test {
base::TimeDelta SwitchOnFreshnessCliff() {
// Add 1, to ensure it meets any greater-than test.
return base::TimeDelta::FromMilliseconds(
- GeolocationArbitratorImpl::kFixStaleTimeoutMilliseconds + 1);
+ LocationArbitratorImpl::kFixStaleTimeoutMilliseconds + 1);
}
MockLocationProvider* cell() {
@@ -147,7 +147,7 @@ class GeolocationLocationArbitratorTest : public testing::Test {
scoped_refptr<FakeAccessTokenStore> access_token_store_;
scoped_ptr<MockLocationObserver> observer_;
- scoped_ptr<TestingGeolocationArbitrator> arbitrator_;
+ scoped_ptr<TestingLocationArbitrator> arbitrator_;
base::MessageLoop loop_;
};
diff --git a/chromium/content/browser/geolocation/mock_location_arbitrator.cc b/chromium/content/browser/geolocation/mock_location_arbitrator.cc
index e0508e11ecf..f48915e07f1 100644
--- a/chromium/content/browser/geolocation/mock_location_arbitrator.cc
+++ b/chromium/content/browser/geolocation/mock_location_arbitrator.cc
@@ -9,24 +9,24 @@
namespace content {
-MockGeolocationArbitrator::MockGeolocationArbitrator()
+MockLocationArbitrator::MockLocationArbitrator()
: permission_granted_(false),
providers_started_(false) {
}
-void MockGeolocationArbitrator::StartProviders(bool use_high_accuracy) {
+void MockLocationArbitrator::StartProviders(bool use_high_accuracy) {
providers_started_ = true;;
}
-void MockGeolocationArbitrator::StopProviders() {
+void MockLocationArbitrator::StopProviders() {
providers_started_ = false;
}
-void MockGeolocationArbitrator::OnPermissionGranted() {
+void MockLocationArbitrator::OnPermissionGranted() {
permission_granted_ = true;
}
-bool MockGeolocationArbitrator::HasPermissionBeenGranted() const {
+bool MockLocationArbitrator::HasPermissionBeenGranted() const {
return permission_granted_;
}
diff --git a/chromium/content/browser/geolocation/mock_location_arbitrator.h b/chromium/content/browser/geolocation/mock_location_arbitrator.h
index 20ef672842a..f096b12f720 100644
--- a/chromium/content/browser/geolocation/mock_location_arbitrator.h
+++ b/chromium/content/browser/geolocation/mock_location_arbitrator.h
@@ -13,13 +13,13 @@ namespace content {
struct Geoposition;
-class MockGeolocationArbitrator : public GeolocationArbitrator {
+class MockLocationArbitrator : public LocationArbitrator {
public:
- MockGeolocationArbitrator();
+ MockLocationArbitrator();
bool providers_started() const { return providers_started_; }
- // GeolocationArbitrator:
+ // LocationArbitrator:
virtual void StartProviders(bool use_high_accuracy)
OVERRIDE;
virtual void StopProviders() OVERRIDE;
@@ -30,7 +30,7 @@ class MockGeolocationArbitrator : public GeolocationArbitrator {
bool permission_granted_;
bool providers_started_;
- DISALLOW_COPY_AND_ASSIGN(MockGeolocationArbitrator);
+ DISALLOW_COPY_AND_ASSIGN(MockLocationArbitrator);
};
} // namespace content
diff --git a/chromium/content/browser/geolocation/mock_location_provider.h b/chromium/content/browser/geolocation/mock_location_provider.h
index 342effcac5d..dd7471fb237 100644
--- a/chromium/content/browser/geolocation/mock_location_provider.h
+++ b/chromium/content/browser/geolocation/mock_location_provider.h
@@ -45,7 +45,7 @@ class MockLocationProvider : public LocationProviderBase {
};
// Factory functions for the various sorts of mock location providers,
-// for use with GeolocationArbitrator::SetProviderFactoryForTest (i.e.
+// for use with LocationArbitrator::SetProviderFactoryForTest (i.e.
// not intended for test code to use to get access to the mock, you can use
// MockLocationProvider::instance_ for this, or make a custom factory method).
diff --git a/chromium/content/browser/geolocation/network_location_provider.cc b/chromium/content/browser/geolocation/network_location_provider.cc
index 82171a062b9..678edb24092 100644
--- a/chromium/content/browser/geolocation/network_location_provider.cc
+++ b/chromium/content/browser/geolocation/network_location_provider.cc
@@ -11,7 +11,7 @@
namespace content {
namespace {
-// The maximum period of time we'll wait for a complete set of device data
+// The maximum period of time we'll wait for a complete set of wifi data
// before sending the request.
const int kDataCompleteWaitSeconds = 2;
} // namespace
@@ -26,7 +26,7 @@ NetworkLocationProvider::PositionCache::~PositionCache() {}
bool NetworkLocationProvider::PositionCache::CachePosition(
const WifiData& wifi_data,
const Geoposition& position) {
- // Check that we can generate a valid key for the device data.
+ // Check that we can generate a valid key for the wifi data.
string16 key;
if (!MakeKey(wifi_data, &key)) {
return false;
@@ -53,8 +53,8 @@ bool NetworkLocationProvider::PositionCache::CachePosition(
return true;
}
-// Searches for a cached position response for the current set of cell ID and
-// WiFi data. Returns the cached position if available, NULL otherwise.
+// Searches for a cached position response for the current WiFi data. Returns
+// the cached position if available, NULL otherwise.
const Geoposition* NetworkLocationProvider::PositionCache::FindPosition(
const WifiData& wifi_data) {
string16 key;
@@ -65,15 +65,14 @@ const Geoposition* NetworkLocationProvider::PositionCache::FindPosition(
return iter == cache_.end() ? NULL : &iter->second;
}
-// Makes the key for the map of cached positions, using a set of
-// device data. Returns true if a good key was generated, false otherwise.
+// Makes the key for the map of cached positions, using the available data.
+// Returns true if a good key was generated, false otherwise.
//
// static
bool NetworkLocationProvider::PositionCache::MakeKey(
const WifiData& wifi_data,
string16* key) {
- // Currently we use only the WiFi data, and base the key only on
- // the MAC addresses.
+ // 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|"
@@ -88,7 +87,7 @@ bool NetworkLocationProvider::PositionCache::MakeKey(
*key += separator;
}
// If the key is the empty string, return false, as we don't want to cache a
- // position for such a set of device data.
+ // position for such data.
return !key->empty();
}
@@ -110,6 +109,9 @@ NetworkLocationProvider::NetworkLocationProvider(
const string16& access_token)
: access_token_store_(access_token_store),
wifi_data_provider_(NULL),
+ wifi_data_update_callback_(
+ base::Bind(&NetworkLocationProvider::WifiDataUpdateAvailable,
+ base::Unretained(this))),
is_wifi_data_complete_(false),
access_token_(access_token),
is_permission_granted_(false),
@@ -118,7 +120,10 @@ NetworkLocationProvider::NetworkLocationProvider(
// Create the position cache.
position_cache_.reset(new PositionCache());
- request_.reset(new NetworkLocationRequest(url_context_getter, url, this));
+ NetworkLocationRequest::LocationResponseCallback callback =
+ base::Bind(&NetworkLocationProvider::LocationResponseAvailable,
+ base::Unretained(this));
+ request_.reset(new NetworkLocationRequest(url_context_getter, url, callback));
}
NetworkLocationProvider::~NetworkLocationProvider() {
@@ -126,7 +131,7 @@ NetworkLocationProvider::~NetworkLocationProvider() {
}
// LocationProvider implementation
-void NetworkLocationProvider::GetPosition(Geoposition *position) {
+void NetworkLocationProvider::GetPosition(Geoposition* position) {
DCHECK(position);
*position = position_;
}
@@ -148,15 +153,13 @@ void NetworkLocationProvider::OnPermissionGranted() {
}
}
-// DeviceDataProviderInterface::ListenerInterface implementation.
-void NetworkLocationProvider::DeviceDataUpdateAvailable(
+void NetworkLocationProvider::WifiDataUpdateAvailable(
WifiDataProvider* provider) {
DCHECK(provider == wifi_data_provider_);
is_wifi_data_complete_ = wifi_data_provider_->GetData(&wifi_data_);
- OnDeviceDataUpdated();
+ OnWifiDataUpdated();
}
-// NetworkLocationRequest::ListenerInterface implementation.
void NetworkLocationProvider::LocationResponseAvailable(
const Geoposition& position,
bool server_error,
@@ -190,26 +193,35 @@ bool NetworkLocationProvider::StartProvider(bool high_accuracy) {
return false;
}
- // Get the device data providers. The first call to Register will create the
- // provider and it will be deleted by ref counting.
- wifi_data_provider_ = WifiDataProvider::Register(this);
+ // Registers a callback with the data provider. The first call to Register
+ // will create a singleton data provider and it will be deleted when the last
+ // callback is removed with Unregister.
+ wifi_data_provider_ = WifiDataProvider::Register(&wifi_data_update_callback_);
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&NetworkLocationProvider::RequestPosition,
weak_factory_.GetWeakPtr()),
base::TimeDelta::FromSeconds(kDataCompleteWaitSeconds));
- // Get the device data.
+ // Get the wifi data.
is_wifi_data_complete_ = wifi_data_provider_->GetData(&wifi_data_);
if (is_wifi_data_complete_)
- OnDeviceDataUpdated();
+ OnWifiDataUpdated();
return true;
}
+void NetworkLocationProvider::OnWifiDataUpdated() {
+ DCHECK(CalledOnValidThread());
+ wifi_data_updated_timestamp_ = base::Time::Now();
+
+ is_new_data_available_ = is_wifi_data_complete_;
+ RequestRefresh();
+}
+
void NetworkLocationProvider::StopProvider() {
DCHECK(CalledOnValidThread());
if (IsStarted()) {
- wifi_data_provider_->Unregister(this);
+ wifi_data_provider_->Unregister(&wifi_data_update_callback_);
}
wifi_data_provider_ = NULL;
weak_factory_.InvalidateWeakPtrs();
@@ -223,7 +235,7 @@ void NetworkLocationProvider::RequestPosition() {
const Geoposition* cached_position =
position_cache_->FindPosition(wifi_data_);
- DCHECK(!device_data_updated_timestamp_.is_null()) <<
+ DCHECK(!wifi_data_updated_timestamp_.is_null()) <<
"Timestamp must be set before looking up position";
if (cached_position) {
DCHECK(cached_position->Validate());
@@ -232,7 +244,7 @@ void NetworkLocationProvider::RequestPosition() {
// The timestamp of a position fix is determined by the timestamp
// of the source data update. (The value of position_.timestamp from
// the cache could be from weeks ago!)
- position_.timestamp = device_data_updated_timestamp_;
+ position_.timestamp = wifi_data_updated_timestamp_;
is_new_data_available_ = false;
// Let listeners know that we now have a position available.
NotifyCallback(position_);
@@ -253,15 +265,7 @@ void NetworkLocationProvider::RequestPosition() {
<< wifi_data_.access_point_data.size();
}
request_->MakeRequest(access_token_, wifi_data_,
- device_data_updated_timestamp_);
-}
-
-void NetworkLocationProvider::OnDeviceDataUpdated() {
- DCHECK(CalledOnValidThread());
- device_data_updated_timestamp_ = base::Time::Now();
-
- is_new_data_available_ = is_wifi_data_complete_;
- RequestRefresh();
+ wifi_data_updated_timestamp_);
}
bool NetworkLocationProvider::IsStarted() const {
diff --git a/chromium/content/browser/geolocation/network_location_provider.h b/chromium/content/browser/geolocation/network_location_provider.h
index a1ba5b38673..d5f3e999d7e 100644
--- a/chromium/content/browser/geolocation/network_location_provider.h
+++ b/chromium/content/browser/geolocation/network_location_provider.h
@@ -15,9 +15,9 @@
#include "base/strings/string16.h"
#include "base/threading/non_thread_safe.h"
#include "base/threading/thread.h"
-#include "content/browser/geolocation/device_data_provider.h"
#include "content/browser/geolocation/location_provider_base.h"
#include "content/browser/geolocation/network_location_request.h"
+#include "content/browser/geolocation/wifi_data_provider.h"
#include "content/common/content_export.h"
#include "content/public/common/geoposition.h"
@@ -27,15 +27,12 @@ class AccessTokenStore;
class NetworkLocationProvider
: public base::NonThreadSafe,
- public LocationProviderBase,
- public WifiDataProvider::ListenerInterface,
- public NetworkLocationRequest::ListenerInterface {
+ public LocationProviderBase {
public:
// Cache of recently resolved locations. Public for tests.
class CONTENT_EXPORT PositionCache {
public:
- // The maximum size of the cache of positions for previously requested
- // device data.
+ // The maximum size of the cache of positions.
static const size_t kMaximumSize;
PositionCache();
@@ -48,19 +45,19 @@ class NetworkLocationProvider
bool CachePosition(const WifiData& wifi_data,
const Geoposition& position);
- // Searches for a cached position response for the current set of device
- // data. Returns NULL if the position is not in the cache, or the cached
+ // Searches for a cached position response for the current set of data.
+ // Returns NULL if the position is not in the cache, or the cached
// position if available. Ownership remains with the cache.
const Geoposition* FindPosition(const WifiData& wifi_data);
private:
// Makes the key for the map of cached positions, using a set of
- // device data. Returns true if a good key was generated, false otherwise.
+ // data. Returns true if a good key was generated, false otherwise.
static bool MakeKey(const WifiData& wifi_data,
string16* key);
// The cache of positions. This is stored as a map keyed on a string that
- // represents a set of device data, and a list to provide
+ // represents a set of data, and a list to provide
// least-recently-added eviction.
typedef std::map<string16, Geoposition> CacheMap;
CacheMap cache_;
@@ -85,31 +82,32 @@ class NetworkLocationProvider
// Satisfies a position request from cache or network.
void RequestPosition();
- // Internal helper used by DeviceDataUpdateAvailable
- void OnDeviceDataUpdated();
+ // Called from a callback when new wifi data is available.
+ void WifiDataUpdateAvailable(WifiDataProvider* provider);
- bool IsStarted() const;
+ // Internal helper used by WifiDataUpdateAvailable.
+ void OnWifiDataUpdated();
- // DeviceDataProvider::ListenerInterface implementation.
- virtual void DeviceDataUpdateAvailable(WifiDataProvider* provider) OVERRIDE;
+ bool IsStarted() const;
- // NetworkLocationRequest::ListenerInterface implementation.
- virtual void LocationResponseAvailable(const Geoposition& position,
- bool server_error,
- const string16& access_token,
- const WifiData& wifi_data) OVERRIDE;
+ void LocationResponseAvailable(const Geoposition& position,
+ bool server_error,
+ const string16& access_token,
+ const WifiData& wifi_data);
scoped_refptr<AccessTokenStore> access_token_store_;
// The wifi data provider, acquired via global factories.
WifiDataProvider* wifi_data_provider_;
- // The wifi data, flags to indicate if the data set is complete.
+ WifiDataProvider::WifiDataUpdateCallback wifi_data_update_callback_;
+
+ // The wifi data and a flag to indicate if the data set is complete.
WifiData wifi_data_;
bool is_wifi_data_complete_;
- // The timestamp for the latest device data update.
- base::Time device_data_updated_timestamp_;
+ // The timestamp for the latest wifi data update.
+ base::Time wifi_data_updated_timestamp_;
// Cached value loaded from the token store or set by a previous server
// response, and sent in each subsequent network request.
@@ -126,10 +124,11 @@ class NetworkLocationProvider
// The network location request object, and the url it uses.
scoped_ptr<NetworkLocationRequest> request_;
- base::WeakPtrFactory<NetworkLocationProvider> weak_factory_;
// The cache of positions.
scoped_ptr<PositionCache> position_cache_;
+ base::WeakPtrFactory<NetworkLocationProvider> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(NetworkLocationProvider);
};
diff --git a/chromium/content/browser/geolocation/network_location_provider_unittest.cc b/chromium/content/browser/geolocation/network_location_provider_unittest.cc
index edfada7766a..f7c732049a8 100644
--- a/chromium/content/browser/geolocation/network_location_provider_unittest.cc
+++ b/chromium/content/browser/geolocation/network_location_provider_unittest.cc
@@ -46,55 +46,49 @@ class MessageLoopQuitListener {
const LocationProvider* updated_provider_;
};
-// A mock implementation of DeviceDataProviderImplBase for testing. Adapted from
+// A mock implementation of WifiDataProviderImplBase for testing. Adapted from
// http://gears.googlecode.com/svn/trunk/gears/geolocation/geolocation_test.cc
-template<typename DataType>
-class MockDeviceDataProviderImpl
- : public DeviceDataProviderImplBase<DataType> {
+class MockWifiDataProviderImpl : public WifiDataProviderImplBase {
public:
- // Factory method for use with DeviceDataProvider::SetFactory.
- static DeviceDataProviderImplBase<DataType>* GetInstance() {
+ // Factory method for use with WifiDataProvider::SetFactory.
+ static WifiDataProviderImplBase* GetInstance() {
CHECK(instance_);
return instance_;
}
- static MockDeviceDataProviderImpl<DataType>* CreateInstance() {
+ static MockWifiDataProviderImpl* CreateInstance() {
CHECK(!instance_);
- instance_ = new MockDeviceDataProviderImpl<DataType>;
+ instance_ = new MockWifiDataProviderImpl;
return instance_;
}
- MockDeviceDataProviderImpl()
+ MockWifiDataProviderImpl()
: start_calls_(0),
stop_calls_(0),
got_data_(true) {
}
- virtual ~MockDeviceDataProviderImpl() {
- CHECK(this == instance_);
- instance_ = NULL;
- }
-
- // DeviceDataProviderImplBase implementation.
- virtual bool StartDataProvider() {
+ // WifiDataProviderImplBase implementation.
+ virtual void StartDataProvider() OVERRIDE {
++start_calls_;
- return true;
}
- virtual void StopDataProvider() {
+
+ virtual void StopDataProvider() OVERRIDE {
++stop_calls_;
}
- virtual bool GetData(DataType* data_out) {
+
+ virtual bool GetData(WifiData* data_out) OVERRIDE {
CHECK(data_out);
*data_out = data_;
return got_data_;
}
- void SetData(const DataType& new_data) {
+ void SetData(const WifiData& new_data) {
got_data_ = true;
const bool differs = data_.DiffersSignificantly(new_data);
data_ = new_data;
if (differs)
- this->NotifyListeners();
+ this->RunCallbacks();
}
void set_got_data(bool got_data) { got_data_ = got_data; }
@@ -102,17 +96,20 @@ class MockDeviceDataProviderImpl
int stop_calls_;
private:
- static MockDeviceDataProviderImpl<DataType>* instance_;
+ virtual ~MockWifiDataProviderImpl() {
+ CHECK(this == instance_);
+ instance_ = NULL;
+ }
+
+ static MockWifiDataProviderImpl* instance_;
- DataType data_;
+ WifiData data_;
bool got_data_;
- DISALLOW_COPY_AND_ASSIGN(MockDeviceDataProviderImpl);
+ DISALLOW_COPY_AND_ASSIGN(MockWifiDataProviderImpl);
};
-template<typename DataType>
-MockDeviceDataProviderImpl<DataType>*
-MockDeviceDataProviderImpl<DataType>::instance_ = NULL;
+MockWifiDataProviderImpl* MockWifiDataProviderImpl::instance_ = NULL;
// Main test fixture
class GeolocationNetworkProviderTest : public testing::Test {
@@ -121,7 +118,7 @@ class GeolocationNetworkProviderTest : public testing::Test {
test_server_url_ = GURL(kTestServerUrl);
access_token_store_ = new FakeAccessTokenStore;
wifi_data_provider_ =
- MockDeviceDataProviderImpl<WifiData>::CreateInstance();
+ MockWifiDataProviderImpl::CreateInstance();
}
virtual void TearDown() {
@@ -143,8 +140,7 @@ class GeolocationNetworkProviderTest : public testing::Test {
GeolocationNetworkProviderTest() {
// TODO(joth): Really these should be in SetUp, not here, but they take no
// effect on Mac OS Release builds if done there. I kid not. Figure out why.
- WifiDataProvider::SetFactory(
- MockDeviceDataProviderImpl<WifiData>::GetInstance);
+ WifiDataProvider::SetFactory(MockWifiDataProviderImpl::GetInstance);
}
// Returns the current url fetcher (if any) and advances the id ready for the
@@ -263,7 +259,7 @@ class GeolocationNetworkProviderTest : public testing::Test {
// Check to see that the api key is being appended for the default
// network provider url.
bool is_default_url = UrlWithoutQuery(request_url) ==
- UrlWithoutQuery(GeolocationArbitratorImpl::DefaultNetworkProviderURL());
+ UrlWithoutQuery(LocationArbitratorImpl::DefaultNetworkProviderURL());
EXPECT_EQ(is_default_url, !request_url.query().empty());
const std::string& upload_data = request.upload_data();
@@ -325,7 +321,7 @@ class GeolocationNetworkProviderTest : public testing::Test {
base::MessageLoop main_message_loop_;
scoped_refptr<FakeAccessTokenStore> access_token_store_;
net::TestURLFetcherFactory url_fetcher_factory_;
- scoped_refptr<MockDeviceDataProviderImpl<WifiData> > wifi_data_provider_;
+ scoped_refptr<MockWifiDataProviderImpl> wifi_data_provider_;
};
TEST_F(GeolocationNetworkProviderTest, CreateDestroy) {
@@ -346,7 +342,7 @@ TEST_F(GeolocationNetworkProviderTest, StartProvider) {
}
TEST_F(GeolocationNetworkProviderTest, StartProviderDefaultUrl) {
- test_server_url_ = GeolocationArbitratorImpl::DefaultNetworkProviderURL();
+ test_server_url_ = LocationArbitratorImpl::DefaultNetworkProviderURL();
scoped_ptr<LocationProvider> provider(CreateProvider(true));
EXPECT_TRUE(provider->StartProvider(false));
net::TestURLFetcher* fetcher = get_url_fetcher_and_advance_id();
@@ -492,7 +488,7 @@ TEST_F(GeolocationNetworkProviderTest, NoRequestOnStartupUntilWifiData) {
}
TEST_F(GeolocationNetworkProviderTest, NewDataReplacesExistingNetworkRequest) {
- // Send initial request with empty device data
+ // Send initial request with empty data
scoped_ptr<LocationProvider> provider(CreateProvider(true));
EXPECT_TRUE(provider->StartProvider(false));
net::TestURLFetcher* fetcher = get_url_fetcher_and_advance_id();
diff --git a/chromium/content/browser/geolocation/network_location_request.cc b/chromium/content/browser/geolocation/network_location_request.cc
index 74a77e1f459..f15141a29e3 100644
--- a/chromium/content/browser/geolocation/network_location_request.cc
+++ b/chromium/content/browser/geolocation/network_location_request.cc
@@ -70,10 +70,10 @@ int NetworkLocationRequest::url_fetcher_id_for_tests = 0;
NetworkLocationRequest::NetworkLocationRequest(
net::URLRequestContextGetter* context,
const GURL& url,
- ListenerInterface* listener)
- : url_context_(context), listener_(listener),
+ LocationResponseCallback callback)
+ : url_context_(context),
+ callback_(callback),
url_(url) {
- DCHECK(listener);
}
NetworkLocationRequest::~NetworkLocationRequest() {
@@ -139,10 +139,8 @@ void NetworkLocationRequest::OnURLFetchComplete(
100);
}
- DCHECK(listener_);
- DVLOG(1) << "NetworkLocationRequest::Run() : Calling listener with position.";
- listener_->LocationResponseAvailable(position, server_error, access_token,
- wifi_data_);
+ DVLOG(1) << "NetworkLocationRequest::OnURLFetchComplete() : run callback.";
+ callback_.Run(position, server_error, access_token, wifi_data_);
}
// Local functions.
@@ -156,7 +154,7 @@ struct AccessPointLess {
};
GURL FormRequestURL(const GURL& url) {
- if (url == GeolocationArbitratorImpl::DefaultNetworkProviderURL()) {
+ if (url == LocationArbitratorImpl::DefaultNetworkProviderURL()) {
std::string api_key = google_apis::GetAPIKey();
if (!api_key.empty()) {
std::string query(url.query());
@@ -273,7 +271,7 @@ void GetLocationFromResponse(bool http_post_result,
FormatPositionError(server_url, message, position);
return;
}
- // We use the timestamp from the device data that was used to generate
+ // We use the timestamp from the wifi data that was used to generate
// this position fix.
if (!ParseServerResponse(response_body, timestamp, position, access_token)) {
// We failed to parse the repsonse.
diff --git a/chromium/content/browser/geolocation/network_location_request.h b/chromium/content/browser/geolocation/network_location_request.h
index 36e843b4351..38aaf3e6ce7 100644
--- a/chromium/content/browser/geolocation/network_location_request.h
+++ b/chromium/content/browser/geolocation/network_location_request.h
@@ -8,7 +8,7 @@
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
-#include "content/browser/geolocation/device_data_provider.h"
+#include "content/browser/geolocation/wifi_data_provider.h"
#include "content/common/content_export.h"
#include "net/url_request/url_fetcher_delegate.h"
#include "url/gurl.h"
@@ -21,31 +21,26 @@ class URLRequestContextGetter;
namespace content {
struct Geoposition;
-// Takes a set of device data and sends it to a server to get a position fix.
+// Takes wifi data and sends it to a server to get a position fix.
// It performs formatting of the request and interpretation of the response.
class NetworkLocationRequest : private net::URLFetcherDelegate {
public:
// ID passed to URLFetcher::Create(). Used for testing.
CONTENT_EXPORT static int url_fetcher_id_for_tests;
- // Interface for receiving callbacks from a NetworkLocationRequest object.
- class ListenerInterface {
- public:
- // Updates the listener with a new position. server_error indicates whether
- // was a server or network error - either no response or a 500 error code.
- virtual void LocationResponseAvailable(
- const Geoposition& position,
- bool server_error,
- const string16& access_token,
- const WifiData& wifi_data) = 0;
-
- protected:
- virtual ~ListenerInterface() {}
- };
+
+ // Called when a new geo position is available. The second argument indicates
+ // whether there was a server error or not. It is true when there was a
+ // 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 WifiData& /* wifi_data */)>
+ LocationResponseCallback;
// |url| is the server address to which the request wil be sent.
NetworkLocationRequest(net::URLRequestContextGetter* context,
const GURL& url,
- ListenerInterface* listener);
+ LocationResponseCallback callback);
virtual ~NetworkLocationRequest();
// Makes a new request. Returns true if the new request was successfully
@@ -62,7 +57,7 @@ class NetworkLocationRequest : private net::URLFetcherDelegate {
virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
scoped_refptr<net::URLRequestContextGetter> url_context_;
- ListenerInterface* listener_;
+ LocationResponseCallback callback_;
const GURL url_;
scoped_ptr<net::URLFetcher> url_fetcher_;
diff --git a/chromium/content/browser/geolocation/device_data_provider.cc b/chromium/content/browser/geolocation/wifi_data.cc
index 00c585bd11d..f4ea267b2f1 100644
--- a/chromium/content/browser/geolocation/device_data_provider.cc
+++ b/chromium/content/browser/geolocation/wifi_data.cc
@@ -1,16 +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 "content/browser/geolocation/device_data_provider.h"
+#include "content/browser/geolocation/wifi_data.h"
-namespace content {
+#include "base/logging.h"
-// statics
-template<> DeviceDataProvider<WifiData>*
- DeviceDataProvider<WifiData>::instance_ = NULL;
-template<> DeviceDataProvider<WifiData>::ImplFactoryFunction
- DeviceDataProvider<WifiData>::factory_function_ = DefaultFactoryFunction;
+namespace content {
AccessPointData::AccessPointData()
: radio_signal_strength(kint32min),
@@ -35,7 +31,7 @@ bool WifiData::DiffersSignificantly(const WifiData& other) const {
min_ap_count / 2);
if (max_ap_count > min_ap_count + difference_threadhold)
return true;
- // Compute size of interesction of old and new sets.
+ // Compute size of intersection of old and new sets.
size_t num_common = 0;
for (AccessPointDataSet::const_iterator iter = access_point_data.begin();
iter != access_point_data.end();
diff --git a/chromium/content/browser/geolocation/wifi_data.h b/chromium/content/browser/geolocation/wifi_data.h
new file mode 100644
index 00000000000..a24e42e2ac1
--- /dev/null
+++ b/chromium/content/browser/geolocation/wifi_data.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_GEOLOCATION_WIFI_DATA_H_
+#define CONTENT_BROWSER_GEOLOCATION_WIFI_DATA_H_
+
+#include <set>
+
+#include "base/basictypes.h"
+#include "base/strings/string16.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+// Wifi data relating to a single access point.
+struct CONTENT_EXPORT AccessPointData {
+ AccessPointData();
+ ~AccessPointData();
+
+ // MAC address, formatted as per MacAddressAsString16.
+ string16 mac_address;
+ int radio_signal_strength; // Measured in dBm
+ int channel;
+ int signal_to_noise; // Ratio in dB
+ string16 ssid; // Network identifier
+};
+
+// This is to allow AccessPointData to be used in std::set. We order
+// lexicographically by MAC address.
+struct AccessPointDataLess {
+ bool operator()(const AccessPointData& data1,
+ const AccessPointData& data2) const {
+ return data1.mac_address < data2.mac_address;
+ }
+};
+
+// All data for wifi.
+struct CONTENT_EXPORT WifiData {
+ WifiData();
+ ~WifiData();
+
+ // Determines whether a new set of WiFi data differs significantly from this.
+ bool DiffersSignificantly(const WifiData& other) const;
+
+ // Store access points as a set, sorted by MAC address. This allows quick
+ // comparison of sets for detecting changes and for caching.
+ typedef std::set<AccessPointData, AccessPointDataLess> AccessPointDataSet;
+ AccessPointDataSet access_point_data;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GEOLOCATION_WIFI_DATA_H_
diff --git a/chromium/content/browser/geolocation/wifi_data_provider.cc b/chromium/content/browser/geolocation/wifi_data_provider.cc
new file mode 100644
index 00000000000..85595f927ab
--- /dev/null
+++ b/chromium/content/browser/geolocation/wifi_data_provider.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/geolocation/wifi_data_provider.h"
+
+namespace content {
+
+// static
+WifiDataProvider* WifiDataProvider::instance_ = NULL;
+
+// static
+WifiDataProvider::ImplFactoryFunction WifiDataProvider::factory_function_ =
+ DefaultFactoryFunction;
+
+// static
+void WifiDataProvider::SetFactory(ImplFactoryFunction factory_function_in) {
+ factory_function_ = factory_function_in;
+}
+
+// static
+void WifiDataProvider::ResetFactory() {
+ factory_function_ = DefaultFactoryFunction;
+}
+
+// static
+WifiDataProvider* WifiDataProvider::Register(WifiDataUpdateCallback* callback) {
+ bool need_to_start_data_provider = false;
+ if (!instance_) {
+ instance_ = new WifiDataProvider();
+ need_to_start_data_provider = true;
+ }
+ DCHECK(instance_);
+ instance_->AddCallback(callback);
+ // Start the provider after adding the callback, to avoid any race in
+ // it running early.
+ if (need_to_start_data_provider)
+ instance_->StartDataProvider();
+ return instance_;
+}
+
+// static
+bool WifiDataProvider::Unregister(WifiDataUpdateCallback* callback) {
+ DCHECK(instance_);
+ DCHECK(instance_->has_callbacks());
+ if (!instance_->RemoveCallback(callback)) {
+ return false;
+ }
+ if (!instance_->has_callbacks()) {
+ // Must stop the data provider (and any implementation threads) before
+ // destroying to avoid any race conditions in access to the provider in
+ // the destructor chain.
+ instance_->StopDataProvider();
+ delete instance_;
+ instance_ = NULL;
+ }
+ return true;
+}
+
+WifiDataProviderImplBase::WifiDataProviderImplBase()
+ : container_(NULL),
+ client_loop_(base::MessageLoop::current()) {
+ DCHECK(client_loop_);
+}
+
+WifiDataProviderImplBase::~WifiDataProviderImplBase() {
+}
+
+void WifiDataProviderImplBase::SetContainer(WifiDataProvider* container) {
+ container_ = container;
+}
+
+void WifiDataProviderImplBase::AddCallback(WifiDataUpdateCallback* callback) {
+ callbacks_.insert(callback);
+}
+
+bool WifiDataProviderImplBase::RemoveCallback(
+ WifiDataUpdateCallback* callback) {
+ return callbacks_.erase(callback) == 1;
+}
+
+bool WifiDataProviderImplBase::has_callbacks() const {
+ return !callbacks_.empty();
+}
+
+void WifiDataProviderImplBase::RunCallbacks() {
+ client_loop_->PostTask(FROM_HERE, base::Bind(
+ &WifiDataProviderImplBase::DoRunCallbacks,
+ this));
+}
+
+bool WifiDataProviderImplBase::CalledOnClientThread() const {
+ return base::MessageLoop::current() == this->client_loop_;
+}
+
+base::MessageLoop* WifiDataProviderImplBase::client_loop() const {
+ return client_loop_;
+}
+
+void WifiDataProviderImplBase::DoRunCallbacks() {
+ // It's possible that all the callbacks (and the container) went away
+ // whilst this task was pending. This is fine; the loop will be a no-op.
+ CallbackSet::const_iterator iter = callbacks_.begin();
+ while (iter != callbacks_.end()) {
+ WifiDataUpdateCallback* callback = *iter;
+ ++iter; // Advance iter before running, in case callback unregisters.
+ callback->Run(container_);
+ }
+}
+
+WifiDataProvider::WifiDataProvider() {
+ DCHECK(factory_function_);
+ impl_ = (*factory_function_)();
+ DCHECK(impl_.get());
+ impl_->SetContainer(this);
+}
+
+WifiDataProvider::~WifiDataProvider() {
+ DCHECK(impl_.get());
+ impl_->SetContainer(NULL);
+}
+
+bool WifiDataProvider::GetData(WifiData* data) {
+ return impl_->GetData(data);
+}
+
+void WifiDataProvider::AddCallback(WifiDataUpdateCallback* callback) {
+ impl_->AddCallback(callback);
+}
+
+bool WifiDataProvider::RemoveCallback(WifiDataUpdateCallback* callback) {
+ return impl_->RemoveCallback(callback);
+}
+
+bool WifiDataProvider::has_callbacks() const {
+ return impl_->has_callbacks();
+}
+
+void WifiDataProvider::StartDataProvider() {
+ impl_->StartDataProvider();
+}
+
+void WifiDataProvider::StopDataProvider() {
+ impl_->StopDataProvider();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/geolocation/wifi_data_provider.h b/chromium/content/browser/geolocation/wifi_data_provider.h
new file mode 100644
index 00000000000..bfb06ec5444
--- /dev/null
+++ b/chromium/content/browser/geolocation/wifi_data_provider.h
@@ -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.
+
+// A wifi data provider provides wifi data from the device that is used by a
+// NetworkLocationProvider to obtain a position fix. We use a singleton
+// instance of the wifi data provider, which is used by multiple
+// NetworkLocationProvider objects.
+//
+// This file provides WifiDataProvider, which provides static methods to
+// access the singleton instance. The singleton instance uses a private
+// implementation to abstract across platforms and also to allow mock providers
+// to be used for testing.
+//
+// This file also provides WifiDataProviderImplBase, a base class which
+// provides common functionality for the private implementations.
+
+#ifndef CONTENT_BROWSER_GEOLOCATION_WIFI_DATA_PROVIDER_H_
+#define CONTENT_BROWSER_GEOLOCATION_WIFI_DATA_PROVIDER_H_
+
+#include <set>
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_util.h"
+#include "content/browser/geolocation/wifi_data.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class WifiDataProvider;
+
+// See class WifiDataProvider for the public client API.
+// WifiDataProvider uses containment to hide platform-specific implementation
+// details from common code. This class provides common functionality for these
+// contained implementation classes. This is a modified pimpl pattern.
+class CONTENT_EXPORT WifiDataProviderImplBase
+ : public base::RefCountedThreadSafe<WifiDataProviderImplBase> {
+ public:
+ WifiDataProviderImplBase();
+
+ // Tells the provider to start looking for data. Callbacks will start
+ // receiving notifications after this call.
+ virtual void StartDataProvider() = 0;
+
+ // Tells the provider to stop looking for data. Callbacks will stop
+ // receiving notifications after this call.
+ virtual void StopDataProvider() = 0;
+
+ // Provides whatever data the provider has, which may be nothing. Return
+ // value indicates whether this is all the data the provider could ever
+ // obtain.
+ virtual bool GetData(WifiData* data) = 0;
+
+ // Sets the container of this class, which is of type WifiDataProvider.
+ // This is required to pass as a parameter when calling a callback.
+ void SetContainer(WifiDataProvider* container);
+
+ typedef base::Callback<void(WifiDataProvider*)> WifiDataUpdateCallback;
+
+ void AddCallback(WifiDataUpdateCallback* callback);
+
+ bool RemoveCallback(WifiDataUpdateCallback* callback);
+
+ bool has_callbacks() const;
+
+ protected:
+ friend class base::RefCountedThreadSafe<WifiDataProviderImplBase>;
+ virtual ~WifiDataProviderImplBase();
+
+ typedef std::set<WifiDataUpdateCallback*> CallbackSet;
+
+ // Runs all callbacks via a posted task, so we can unwind callstack here and
+ // avoid client reentrancy.
+ void RunCallbacks();
+
+ bool CalledOnClientThread() const;
+
+ base::MessageLoop* client_loop() const;
+
+ private:
+ void DoRunCallbacks();
+
+ WifiDataProvider* container_;
+
+ // Reference to the client's message loop. All callbacks should happen in this
+ // context.
+ base::MessageLoop* client_loop_;
+
+ CallbackSet callbacks_;
+
+ DISALLOW_COPY_AND_ASSIGN(WifiDataProviderImplBase);
+};
+
+// A wifi data provider
+//
+// We use a singleton instance of this class which is shared by multiple network
+// location providers. These location providers access the instance through the
+// Register and Unregister methods.
+class CONTENT_EXPORT WifiDataProvider {
+ public:
+ // Sets the factory function which will be used by Register to create the
+ // implementation used by the singleton instance. This factory approach is
+ // used both to abstract accross platform-specific implementations and to
+ // inject mock implementations for testing.
+ typedef WifiDataProviderImplBase* (*ImplFactoryFunction)(void);
+ static void SetFactory(ImplFactoryFunction factory_function_in);
+
+ // Resets the factory function to the default.
+ static void ResetFactory();
+
+ typedef base::Callback<void(WifiDataProvider*)> WifiDataUpdateCallback;
+
+ // Registers a callback, which will be run whenever new data is available.
+ // Instantiates the singleton if necessary, and always returns it.
+ static WifiDataProvider* Register(WifiDataUpdateCallback* callback);
+
+ // Removes a callback. If this is the last callback, deletes the singleton
+ // instance. Return value indicates success.
+ static bool Unregister(WifiDataUpdateCallback* callback);
+
+ // Provides whatever data the provider has, which may be nothing. Return
+ // value indicates whether this is all the data the provider could ever
+ // obtain.
+ bool GetData(WifiData* data);
+
+ private:
+ // Private constructor and destructor, callers access singleton through
+ // Register and Unregister.
+ WifiDataProvider();
+ virtual ~WifiDataProvider();
+
+ void AddCallback(WifiDataUpdateCallback* callback);
+ bool RemoveCallback(WifiDataUpdateCallback* callback);
+ bool has_callbacks() const;
+
+ void StartDataProvider();
+ void StopDataProvider();
+
+ static WifiDataProviderImplBase* DefaultFactoryFunction();
+
+ // The singleton-like instance of this class. (Not 'true' singleton, as it
+ // may go through multiple create/destroy/create cycles per process instance,
+ // e.g. when under test).
+ static WifiDataProvider* instance_;
+
+ // The factory function used to create the singleton instance.
+ static ImplFactoryFunction factory_function_;
+
+ // The internal implementation.
+ scoped_refptr<WifiDataProviderImplBase> impl_;
+
+ DISALLOW_COPY_AND_ASSIGN(WifiDataProvider);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GEOLOCATION_WIFI_DATA_PROVIDER_H_
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_chromeos.cc b/chromium/content/browser/geolocation/wifi_data_provider_chromeos.cc
index b4222d7a01b..a8b20414ceb 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_chromeos.cc
+++ b/chromium/content/browser/geolocation/wifi_data_provider_chromeos.cc
@@ -29,18 +29,17 @@ WifiDataProviderChromeOs::WifiDataProviderChromeOs() : started_(false) {
WifiDataProviderChromeOs::~WifiDataProviderChromeOs() {
}
-bool WifiDataProviderChromeOs::StartDataProvider() {
+void WifiDataProviderChromeOs::StartDataProvider() {
DCHECK(CalledOnClientThread());
DCHECK(polling_policy_ == NULL);
polling_policy_.reset(
- new GenericPollingPolicy<kDefaultPollingIntervalMilliseconds,
- kNoChangePollingIntervalMilliseconds,
- kTwoNoChangePollingIntervalMilliseconds,
- kNoWifiPollingIntervalMilliseconds>);
+ new GenericWifiPollingPolicy<kDefaultPollingIntervalMilliseconds,
+ kNoChangePollingIntervalMilliseconds,
+ kTwoNoChangePollingIntervalMilliseconds,
+ kNoWifiPollingIntervalMilliseconds>);
ScheduleStart();
- return true;
}
void WifiDataProviderChromeOs::StopDataProvider() {
@@ -71,14 +70,14 @@ void WifiDataProviderChromeOs::DoWifiScanTaskOnUIThread() {
WifiData new_data;
- if (!GetAccessPointData(&new_data.access_point_data)) {
+ if (GetAccessPointData(&new_data.access_point_data)) {
client_loop()->PostTask(
FROM_HERE,
- base::Bind(&WifiDataProviderChromeOs::DidWifiScanTaskNoResults, this));
+ base::Bind(&WifiDataProviderChromeOs::DidWifiScanTask, this, new_data));
} else {
client_loop()->PostTask(
FROM_HERE,
- base::Bind(&WifiDataProviderChromeOs::DidWifiScanTask, this, new_data));
+ base::Bind(&WifiDataProviderChromeOs::DidWifiScanTaskNoResults, this));
}
}
@@ -88,7 +87,6 @@ void WifiDataProviderChromeOs::DidWifiScanTaskNoResults() {
// in between DoWifiScanTaskOnUIThread and this method).
if (started_)
ScheduleNextScan(polling_policy_->NoWifiInterval());
- MaybeNotifyListeners(false);
}
void WifiDataProviderChromeOs::DidWifiScanTask(const WifiData& new_data) {
@@ -101,13 +99,10 @@ void WifiDataProviderChromeOs::DidWifiScanTask(const WifiData& new_data) {
polling_policy_->UpdatePollingInterval(update_available);
ScheduleNextScan(polling_policy_->PollingInterval());
}
- MaybeNotifyListeners(update_available);
-}
-void WifiDataProviderChromeOs::MaybeNotifyListeners(bool update_available) {
if (update_available || !is_first_scan_complete_) {
is_first_scan_complete_ = true;
- NotifyListeners();
+ RunCallbacks();
}
}
@@ -141,9 +136,12 @@ void WifiDataProviderChromeOs::ScheduleStart() {
bool WifiDataProviderChromeOs::GetAccessPointData(
WifiData::AccessPointDataSet* result) {
- chromeos::WifiAccessPointVector access_points;
+ // If wifi isn't enabled, we've effectively completed the task.
+ // Return true to indicate an empty access point list.
if (!chromeos::NetworkHandler::Get()->geolocation_handler()->wifi_enabled())
- return false;
+ return true;
+
+ chromeos::WifiAccessPointVector access_points;
int64 age_ms = 0;
if (!chromeos::NetworkHandler::Get()->geolocation_handler()->
GetWifiAccessPoints(&access_points, &age_ms)) {
@@ -168,7 +166,6 @@ bool WifiDataProviderChromeOs::GetAccessPointData(
}
// static
-template<>
WifiDataProviderImplBase* WifiDataProvider::DefaultFactoryFunction() {
return new WifiDataProviderChromeOs();
}
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_chromeos.h b/chromium/content/browser/geolocation/wifi_data_provider_chromeos.h
index ac8902c9874..895d06eaf31 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_chromeos.h
+++ b/chromium/content/browser/geolocation/wifi_data_provider_chromeos.h
@@ -6,7 +6,8 @@
#define CONTENT_BROWSER_GEOLOCATION_WIFI_DATA_PROVIDER_CHROMEOS_H_
#include "base/compiler_specific.h"
-#include "content/browser/geolocation/wifi_data_provider_common.h"
+#include "content/browser/geolocation/wifi_data_provider.h"
+#include "content/browser/geolocation/wifi_polling_policy.h"
namespace content {
@@ -16,7 +17,7 @@ class CONTENT_EXPORT WifiDataProviderChromeOs
WifiDataProviderChromeOs();
// WifiDataProviderImplBase
- virtual bool StartDataProvider() OVERRIDE;
+ virtual void StartDataProvider() OVERRIDE;
virtual void StopDataProvider() OVERRIDE;
virtual bool GetData(WifiData* data) OVERRIDE;
@@ -31,7 +32,6 @@ class CONTENT_EXPORT WifiDataProviderChromeOs
// Client thread
void DidWifiScanTaskNoResults();
void DidWifiScanTask(const WifiData& new_data);
- void MaybeNotifyListeners(bool update_available);
// Will schedule a scan; i.e. enqueue DoWifiScanTask deferred task.
void ScheduleNextScan(int interval);
@@ -45,11 +45,8 @@ class CONTENT_EXPORT WifiDataProviderChromeOs
// Get access point data from chromeos.
bool GetAccessPointData(WifiData::AccessPointDataSet* data);
- // Underlying OS wifi API. (UI thread)
- scoped_ptr<WifiDataProviderCommon::WlanApiInterface> wlan_api_;
-
// Controls the polling update interval. (client thread)
- scoped_ptr<PollingPolicyInterface> polling_policy_;
+ scoped_ptr<WifiPollingPolicy> polling_policy_;
// The latest wifi data. (client thread)
WifiData wifi_data_;
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_chromeos_unittest.cc b/chromium/content/browser/geolocation/wifi_data_provider_chromeos_unittest.cc
index 541b28422b2..f9deb663539 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_chromeos_unittest.cc
+++ b/chromium/content/browser/geolocation/wifi_data_provider_chromeos_unittest.cc
@@ -54,7 +54,7 @@ class GeolocationChromeOsWifiDataProviderTest : public testing::Test {
shill::kGeoChannelProperty, channel);
properties.SetStringWithoutPathExpansion(
shill::kGeoSignalStrengthProperty, strength);
- manager_test_->AddGeoNetwork(flimflam::kTypeWifi, properties);
+ manager_test_->AddGeoNetwork(shill::kTypeWifi, properties);
}
}
message_loop_.RunUntilIdle();
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_common.cc b/chromium/content/browser/geolocation/wifi_data_provider_common.cc
index 2642176358c..31f969c3a3c 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_common.cc
+++ b/chromium/content/browser/geolocation/wifi_data_provider_common.cc
@@ -25,40 +25,14 @@ string16 MacAddressAsString16(const uint8 mac_as_int[6]) {
}
WifiDataProviderCommon::WifiDataProviderCommon()
- : Thread("Geolocation_wifi_provider"),
- is_first_scan_complete_(false),
+ : is_first_scan_complete_(false),
weak_factory_(this) {
}
WifiDataProviderCommon::~WifiDataProviderCommon() {
- // Thread must be stopped before entering destructor chain to avoid race
- // conditions; see comment in DeviceDataProvider::Unregister.
- DCHECK(!IsRunning()); // Must call StopDataProvider before destroying me.
}
-bool WifiDataProviderCommon::StartDataProvider() {
- DCHECK(CalledOnClientThread());
- DCHECK(!IsRunning()); // StartDataProvider must only be called once.
- return Start();
-}
-
-void WifiDataProviderCommon::StopDataProvider() {
- DCHECK(CalledOnClientThread());
- Stop();
-}
-
-bool WifiDataProviderCommon::GetData(WifiData* data) {
- DCHECK(CalledOnClientThread());
- DCHECK(data);
- base::AutoLock lock(data_mutex_);
- *data = wifi_data_;
- // If we've successfully completed a scan, indicate that we have all of the
- // data we can get.
- return is_first_scan_complete_;
-}
-
-// Thread implementation
-void WifiDataProviderCommon::Init() {
+void WifiDataProviderCommon::StartDataProvider() {
DCHECK(wlan_api_ == NULL);
wlan_api_.reset(NewWlanApi());
if (wlan_api_ == NULL) {
@@ -76,34 +50,37 @@ void WifiDataProviderCommon::Init() {
ScheduleNextScan(0);
}
-void WifiDataProviderCommon::CleanUp() {
- // Destroy these instances in the thread on which they were created.
+void WifiDataProviderCommon::StopDataProvider() {
wlan_api_.reset();
polling_policy_.reset();
}
+bool WifiDataProviderCommon::GetData(WifiData* data) {
+ *data = wifi_data_;
+ // If we've successfully completed a scan, indicate that we have all of the
+ // data we can get.
+ return is_first_scan_complete_;
+}
+
void WifiDataProviderCommon::DoWifiScanTask() {
bool update_available = false;
WifiData new_data;
if (!wlan_api_->GetAccessPointData(&new_data.access_point_data)) {
ScheduleNextScan(polling_policy_->NoWifiInterval());
} else {
- {
- base::AutoLock lock(data_mutex_);
- update_available = wifi_data_.DiffersSignificantly(new_data);
- wifi_data_ = new_data;
- }
+ update_available = wifi_data_.DiffersSignificantly(new_data);
+ wifi_data_ = new_data;
polling_policy_->UpdatePollingInterval(update_available);
ScheduleNextScan(polling_policy_->PollingInterval());
}
if (update_available || !is_first_scan_complete_) {
is_first_scan_complete_ = true;
- NotifyListeners();
+ RunCallbacks();
}
}
void WifiDataProviderCommon::ScheduleNextScan(int interval) {
- message_loop()->PostDelayedTask(
+ client_loop()->PostDelayedTask(
FROM_HERE,
base::Bind(&WifiDataProviderCommon::DoWifiScanTask,
weak_factory_.GetWeakPtr()),
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_common.h b/chromium/content/browser/geolocation/wifi_data_provider_common.h
index e4bed573201..c42b4c2a851 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_common.h
+++ b/chromium/content/browser/geolocation/wifi_data_provider_common.h
@@ -11,8 +11,8 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
-#include "base/threading/thread.h"
-#include "content/browser/geolocation/device_data_provider.h"
+#include "content/browser/geolocation/wifi_data_provider.h"
+#include "content/browser/geolocation/wifi_polling_policy.h"
#include "content/common/content_export.h"
namespace content {
@@ -20,55 +20,12 @@ namespace content {
// Converts a MAC address stored as an array of uint8 to a string.
string16 MacAddressAsString16(const uint8 mac_as_int[6]);
-// Allows sharing and mocking of the update polling policy function.
-class PollingPolicyInterface {
- public:
- virtual ~PollingPolicyInterface() {}
- // Calculates the new polling interval for wiFi scans, given the previous
- // interval and whether the last scan produced new results.
- virtual void UpdatePollingInterval(bool scan_results_differ) = 0;
- virtual int PollingInterval() = 0;
- virtual int NoWifiInterval() = 0;
-};
-
-// Generic polling policy, constants are compile-time parameterized to allow
-// tuning on a per-platform basis.
-template<int DEFAULT_INTERVAL,
- int NO_CHANGE_INTERVAL,
- int TWO_NO_CHANGE_INTERVAL,
- int NO_WIFI_INTERVAL>
-class GenericPollingPolicy : public PollingPolicyInterface {
- public:
- GenericPollingPolicy() : polling_interval_(DEFAULT_INTERVAL) {}
- // PollingPolicyInterface
- virtual void UpdatePollingInterval(bool scan_results_differ) {
- if (scan_results_differ) {
- polling_interval_ = DEFAULT_INTERVAL;
- } else if (polling_interval_ == DEFAULT_INTERVAL) {
- polling_interval_ = NO_CHANGE_INTERVAL;
- } else {
- DCHECK(polling_interval_ == NO_CHANGE_INTERVAL ||
- polling_interval_ == TWO_NO_CHANGE_INTERVAL);
- polling_interval_ = TWO_NO_CHANGE_INTERVAL;
- }
- }
- virtual int PollingInterval() { return polling_interval_; }
- virtual int NoWifiInterval() { return NO_WIFI_INTERVAL; }
-
- private:
- int polling_interval_;
-};
-
// Base class to promote code sharing between platform specific wifi data
// providers. It's optional for specific platforms to derive this, but if they
-// do threading and polling is taken care of by this base class, and all the
-// platform need do is provide the underlying WLAN access API and policy policy,
-// both of which will be create & accessed in the worker thread (only).
-// Also designed this way to promotes ease of testing the cross-platform
-// behavior w.r.t. polling & threading.
-class CONTENT_EXPORT WifiDataProviderCommon
- : public WifiDataProviderImplBase,
- private base::Thread {
+// do polling behavior is taken care of by this base class, and all the platform
+// need do is provide the underlying WLAN access API and polling policy.
+// Also designed this way for ease of testing the cross-platform behavior.
+class CONTENT_EXPORT WifiDataProviderCommon : public WifiDataProviderImplBase {
public:
// Interface to abstract the low level data OS library call, and to allow
// mocking (hence public).
@@ -82,44 +39,38 @@ class CONTENT_EXPORT WifiDataProviderCommon
WifiDataProviderCommon();
// WifiDataProviderImplBase implementation
- virtual bool StartDataProvider() OVERRIDE;
+ virtual void StartDataProvider() OVERRIDE;
virtual void StopDataProvider() OVERRIDE;
virtual bool GetData(WifiData* data) OVERRIDE;
protected:
virtual ~WifiDataProviderCommon();
- // Returns ownership. Will be called from the worker thread.
+ // Returns ownership.
virtual WlanApiInterface* NewWlanApi() = 0;
- // Returns ownership. Will be called from the worker thread.
- virtual PollingPolicyInterface* NewPollingPolicy() = 0;
+ // Returns ownership.
+ virtual WifiPollingPolicy* NewPollingPolicy() = 0;
private:
- // Thread implementation
- virtual void Init() OVERRIDE;
- virtual void CleanUp() OVERRIDE;
-
- // Task which run in the child thread.
+ // Runs a scan. Calls the callbacks if new data is found.
void DoWifiScanTask();
// Will schedule a scan; i.e. enqueue DoWifiScanTask deferred task.
void ScheduleNextScan(int interval);
WifiData wifi_data_;
- base::Lock data_mutex_;
- // Whether we've successfully completed a scan for WiFi data (or the polling
- // thread has terminated early).
+ // Whether we've successfully completed a scan for WiFi data.
bool is_first_scan_complete_;
// Underlying OS wifi API.
scoped_ptr<WlanApiInterface> wlan_api_;
// Controls the polling update interval.
- scoped_ptr<PollingPolicyInterface> polling_policy_;
+ scoped_ptr<WifiPollingPolicy> polling_policy_;
- // Holder for the tasks which run on the thread; takes care of cleanup.
+ // Holder for delayed tasks; takes care of cleanup.
base::WeakPtrFactory<WifiDataProviderCommon> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(WifiDataProviderCommon);
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_common_unittest.cc b/chromium/content/browser/geolocation/wifi_data_provider_common_unittest.cc
index 9d1b9fbcc7b..61e236f98a8 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_common_unittest.cc
+++ b/chromium/content/browser/geolocation/wifi_data_provider_common_unittest.cc
@@ -42,7 +42,7 @@ class MockWlanApi : public WifiDataProviderCommon::WlanApiInterface {
}
};
-class MockPollingPolicy :public PollingPolicyInterface {
+class MockPollingPolicy : public WifiPollingPolicy {
public:
MockPollingPolicy() {
ON_CALL(*this,PollingInterval())
@@ -57,27 +57,25 @@ class MockPollingPolicy :public PollingPolicyInterface {
virtual void UpdatePollingInterval(bool) {}
};
-// Stops the specified (nested) message loop when the listener is called back.
-class MessageLoopQuitListener
- : public WifiDataProviderCommon::ListenerInterface {
+// Stops the specified (nested) message loop when the callback is called.
+class MessageLoopQuitter {
public:
- explicit MessageLoopQuitListener(base::MessageLoop* message_loop)
- : message_loop_to_quit_(message_loop) {
+ explicit MessageLoopQuitter(base::MessageLoop* message_loop)
+ : message_loop_to_quit_(message_loop),
+ callback_(base::Bind(&MessageLoopQuitter::WifiDataUpdateAvailable,
+ base::Unretained(this))) {
CHECK(message_loop_to_quit_ != NULL);
}
- // ListenerInterface
- virtual void DeviceDataUpdateAvailable(
- DeviceDataProvider<WifiData>* provider) OVERRIDE {
+
+ void WifiDataUpdateAvailable(WifiDataProvider* provider) {
// Provider should call back on client's thread.
EXPECT_EQ(base::MessageLoop::current(), message_loop_to_quit_);
- provider_ = provider;
message_loop_to_quit_->QuitNow();
}
base::MessageLoop* message_loop_to_quit_;
- DeviceDataProvider<WifiData>* provider_;
+ WifiDataProvider::WifiDataUpdateCallback callback_;
};
-
class WifiDataProviderCommonWithMock : public WifiDataProviderCommon {
public:
WifiDataProviderCommonWithMock()
@@ -89,7 +87,7 @@ class WifiDataProviderCommonWithMock : public WifiDataProviderCommon {
CHECK(new_wlan_api_ != NULL);
return new_wlan_api_.release();
}
- virtual PollingPolicyInterface* NewPollingPolicy() OVERRIDE {
+ virtual WifiPollingPolicy* NewPollingPolicy() OVERRIDE {
CHECK(new_polling_policy_ != NULL);
return new_polling_policy_.release();
}
@@ -111,24 +109,24 @@ WifiDataProviderImplBase* CreateWifiDataProviderCommonWithMock() {
class GeolocationWifiDataProviderCommonTest : public testing::Test {
public:
GeolocationWifiDataProviderCommonTest()
- : quit_listener_(&main_message_loop_) {
+ : loop_quitter_(&main_message_loop_) {
}
virtual void SetUp() {
provider_ = new WifiDataProviderCommonWithMock;
wlan_api_ = provider_->new_wlan_api_.get();
polling_policy_ = provider_->new_polling_policy_.get();
- provider_->AddListener(&quit_listener_);
+ provider_->AddCallback(&loop_quitter_.callback_);
}
virtual void TearDown() {
- provider_->RemoveListener(&quit_listener_);
+ provider_->RemoveCallback(&loop_quitter_.callback_);
provider_->StopDataProvider();
provider_ = NULL;
}
protected:
base::MessageLoop main_message_loop_;
- MessageLoopQuitListener quit_listener_;
+ MessageLoopQuitter loop_quitter_;
scoped_refptr<WifiDataProviderCommonWithMock> provider_;
MockWlanApi* wlan_api_;
MockPollingPolicy* polling_policy_;
@@ -141,12 +139,12 @@ TEST_F(GeolocationWifiDataProviderCommonTest, CreateDestroy) {
EXPECT_TRUE(NULL != wlan_api_);
}
-TEST_F(GeolocationWifiDataProviderCommonTest, StartThread) {
+TEST_F(GeolocationWifiDataProviderCommonTest, RunNormal) {
EXPECT_CALL(*wlan_api_, GetAccessPointData(_))
.Times(AtLeast(1));
EXPECT_CALL(*polling_policy_, PollingInterval())
.Times(AtLeast(1));
- EXPECT_TRUE(provider_->StartDataProvider());
+ provider_->StartDataProvider();
main_message_loop_.Run();
SUCCEED();
}
@@ -188,11 +186,9 @@ TEST_F(GeolocationWifiDataProviderCommonTest, DoAnEmptyScan) {
.Times(AtLeast(1));
EXPECT_CALL(*polling_policy_, PollingInterval())
.Times(AtLeast(1));
- EXPECT_TRUE(provider_->StartDataProvider());
+ provider_->StartDataProvider();
main_message_loop_.Run();
- // Check we had at least one call. The worker thread may have raced ahead
- // and made multiple calls.
- EXPECT_GT(wlan_api_->calls_, 0);
+ EXPECT_EQ(wlan_api_->calls_, 1);
WifiData data;
EXPECT_TRUE(provider_->GetData(&data));
EXPECT_EQ(0, static_cast<int>(data.access_point_data.size()));
@@ -211,23 +207,22 @@ TEST_F(GeolocationWifiDataProviderCommonTest, DoScanWithResults) {
single_access_point.ssid = ASCIIToUTF16("foossid");
wlan_api_->data_out_.insert(single_access_point);
- EXPECT_TRUE(provider_->StartDataProvider());
+ provider_->StartDataProvider();
main_message_loop_.Run();
- EXPECT_GT(wlan_api_->calls_, 0);
+ EXPECT_EQ(wlan_api_->calls_, 1);
WifiData data;
EXPECT_TRUE(provider_->GetData(&data));
EXPECT_EQ(1, static_cast<int>(data.access_point_data.size()));
EXPECT_EQ(single_access_point.ssid, data.access_point_data.begin()->ssid);
}
-TEST_F(GeolocationWifiDataProviderCommonTest,
- StartThreadViaDeviceDataProvider) {
- MessageLoopQuitListener quit_listener(&main_message_loop_);
+TEST_F(GeolocationWifiDataProviderCommonTest, RegisterUnregister) {
+ MessageLoopQuitter loop_quitter(&main_message_loop_);
WifiDataProvider::SetFactory(CreateWifiDataProviderCommonWithMock);
- DeviceDataProvider<WifiData>::Register(&quit_listener);
+ WifiDataProvider::Register(&loop_quitter.callback_);
main_message_loop_.Run();
- DeviceDataProvider<WifiData>::Unregister(&quit_listener);
- DeviceDataProvider<WifiData>::ResetFactory();
+ WifiDataProvider::Unregister(&loop_quitter.callback_);
+ WifiDataProvider::ResetFactory();
}
} // namespace content
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_common_win.cc b/chromium/content/browser/geolocation/wifi_data_provider_common_win.cc
index 9ac7848835d..a0d334f0c44 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_common_win.cc
+++ b/chromium/content/browser/geolocation/wifi_data_provider_common_win.cc
@@ -7,7 +7,6 @@
#include <assert.h>
#include "base/strings/utf_string_conversions.h"
-#include "content/browser/geolocation/device_data_provider.h"
#include "content/browser/geolocation/wifi_data_provider_common.h"
namespace content {
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_common_win.h b/chromium/content/browser/geolocation/wifi_data_provider_common_win.h
index f58e0c6d2b2..24973a57feb 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_common_win.h
+++ b/chromium/content/browser/geolocation/wifi_data_provider_common_win.h
@@ -8,7 +8,7 @@
#include <windows.h>
#include <ntddndis.h>
-#include "content/browser/geolocation/device_data_provider.h"
+#include "content/browser/geolocation/wifi_data_provider.h"
namespace content {
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_linux.cc b/chromium/content/browser/geolocation/wifi_data_provider_linux.cc
index edece1d0211..a8d2135fc92 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_linux.cc
+++ b/chromium/content/browser/geolocation/wifi_data_provider_linux.cc
@@ -344,7 +344,6 @@ scoped_ptr<dbus::Response> NetworkManagerWlanApi::GetAccessPointProperty(
} // namespace
// static
-template<>
WifiDataProviderImplBase* WifiDataProvider::DefaultFactoryFunction() {
return new WifiDataProviderLinux();
}
@@ -363,11 +362,11 @@ WifiDataProviderLinux::NewWlanApi() {
return NULL;
}
-PollingPolicyInterface* WifiDataProviderLinux::NewPollingPolicy() {
- return new GenericPollingPolicy<kDefaultPollingIntervalMilliseconds,
- kNoChangePollingIntervalMilliseconds,
- kTwoNoChangePollingIntervalMilliseconds,
- kNoWifiPollingIntervalMilliseconds>;
+WifiPollingPolicy* WifiDataProviderLinux::NewPollingPolicy() {
+ return new GenericWifiPollingPolicy<kDefaultPollingIntervalMilliseconds,
+ kNoChangePollingIntervalMilliseconds,
+ kTwoNoChangePollingIntervalMilliseconds,
+ kNoWifiPollingIntervalMilliseconds>;
}
WifiDataProviderCommon::WlanApiInterface*
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_linux.h b/chromium/content/browser/geolocation/wifi_data_provider_linux.h
index 526f61074af..40f6f14e75f 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_linux.h
+++ b/chromium/content/browser/geolocation/wifi_data_provider_linux.h
@@ -26,7 +26,7 @@ class CONTENT_EXPORT WifiDataProviderLinux : public WifiDataProviderCommon {
// WifiDataProviderCommon
virtual WlanApiInterface* NewWlanApi() OVERRIDE;
- virtual PollingPolicyInterface* NewPollingPolicy() OVERRIDE;
+ virtual WifiPollingPolicy* NewPollingPolicy() OVERRIDE;
// For testing.
WlanApiInterface* NewWlanApiForTesting(dbus::Bus* bus);
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_mac.cc b/chromium/content/browser/geolocation/wifi_data_provider_mac.cc
index 8f81305ac3a..e7d8e8247f9 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_mac.cc
+++ b/chromium/content/browser/geolocation/wifi_data_provider_mac.cc
@@ -158,7 +158,6 @@ bool Apple80211Api::GetAccessPointData(WifiData::AccessPointDataSet* data) {
} // namespace
// static
-template<>
WifiDataProviderImplBase* WifiDataProvider::DefaultFactoryFunction() {
return new MacWifiDataProvider();
}
@@ -185,11 +184,11 @@ MacWifiDataProvider::WlanApiInterface* MacWifiDataProvider::NewWlanApi() {
return NULL;
}
-PollingPolicyInterface* MacWifiDataProvider::NewPollingPolicy() {
- return new GenericPollingPolicy<kDefaultPollingInterval,
- kNoChangePollingInterval,
- kTwoNoChangePollingInterval,
- kNoWifiPollingIntervalMilliseconds>;
+WifiPollingPolicy* MacWifiDataProvider::NewPollingPolicy() {
+ return new GenericWifiPollingPolicy<kDefaultPollingInterval,
+ kNoChangePollingInterval,
+ kTwoNoChangePollingInterval,
+ kNoWifiPollingIntervalMilliseconds>;
}
} // namespace content
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_mac.h b/chromium/content/browser/geolocation/wifi_data_provider_mac.h
index e36bd8ca584..ebb0030df2f 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_mac.h
+++ b/chromium/content/browser/geolocation/wifi_data_provider_mac.h
@@ -21,7 +21,7 @@ class MacWifiDataProvider : public WifiDataProviderCommon {
// WifiDataProviderCommon
virtual WlanApiInterface* NewWlanApi() OVERRIDE;
- virtual PollingPolicyInterface* NewPollingPolicy() OVERRIDE;
+ virtual WifiPollingPolicy* NewPollingPolicy() OVERRIDE;
DISALLOW_COPY_AND_ASSIGN(MacWifiDataProvider);
};
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_win.cc b/chromium/content/browser/geolocation/wifi_data_provider_win.cc
index a35e6e948f6..8efb1918450 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_win.cc
+++ b/chromium/content/browser/geolocation/wifi_data_provider_win.cc
@@ -158,7 +158,6 @@ bool ResizeBuffer(int requested_size, scoped_ptr_malloc<BYTE>* buffer);
bool GetSystemDirectory(string16* path);
} // namespace
-template<>
WifiDataProviderImplBase* WifiDataProvider::DefaultFactoryFunction() {
return new Win32WifiDataProvider();
}
@@ -179,11 +178,11 @@ WifiDataProviderCommon::WlanApiInterface* Win32WifiDataProvider::NewWlanApi() {
return WindowsNdisApi::Create();
}
-PollingPolicyInterface* Win32WifiDataProvider::NewPollingPolicy() {
- return new GenericPollingPolicy<kDefaultPollingInterval,
- kNoChangePollingInterval,
- kTwoNoChangePollingInterval,
- kNoWifiPollingIntervalMilliseconds>;
+WifiPollingPolicy* Win32WifiDataProvider::NewPollingPolicy() {
+ return new GenericWifiPollingPolicy<kDefaultPollingInterval,
+ kNoChangePollingInterval,
+ kTwoNoChangePollingInterval,
+ kNoWifiPollingIntervalMilliseconds>;
}
// Local classes and functions
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_win.h b/chromium/content/browser/geolocation/wifi_data_provider_win.h
index 3fbb9cec99d..c39bd580a79 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_win.h
+++ b/chromium/content/browser/geolocation/wifi_data_provider_win.h
@@ -9,7 +9,6 @@
#include "content/common/content_export.h"
namespace content {
-class PollingPolicyInterface;
class CONTENT_EXPORT Win32WifiDataProvider : public WifiDataProviderCommon {
public:
@@ -20,7 +19,7 @@ class CONTENT_EXPORT Win32WifiDataProvider : public WifiDataProviderCommon {
// WifiDataProviderCommon
virtual WlanApiInterface* NewWlanApi();
- virtual PollingPolicyInterface* NewPollingPolicy();
+ virtual WifiPollingPolicy* NewPollingPolicy();
DISALLOW_COPY_AND_ASSIGN(Win32WifiDataProvider);
};
diff --git a/chromium/content/browser/geolocation/wifi_polling_policy.h b/chromium/content/browser/geolocation/wifi_polling_policy.h
new file mode 100644
index 00000000000..c1df4d267ac
--- /dev/null
+++ b/chromium/content/browser/geolocation/wifi_polling_policy.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_GEOLOCATION_WIFI_POLLING_POLICY_H_
+#define CONTENT_BROWSER_GEOLOCATION_WIFI_POLLING_POLICY_H_
+
+namespace content {
+
+// Allows sharing and mocking of the update polling policy function.
+class WifiPollingPolicy {
+ public:
+ WifiPollingPolicy() {}
+ virtual ~WifiPollingPolicy() {}
+ // Calculates the new polling interval for wiFi scans, given the previous
+ // interval and whether the last scan produced new results.
+ virtual void UpdatePollingInterval(bool scan_results_differ) = 0;
+ virtual int PollingInterval() = 0;
+ virtual int NoWifiInterval() = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WifiPollingPolicy);
+};
+
+// Generic polling policy, constants are compile-time parameterized to allow
+// tuning on a per-platform basis.
+template<int DEFAULT_INTERVAL,
+ int NO_CHANGE_INTERVAL,
+ int TWO_NO_CHANGE_INTERVAL,
+ int NO_WIFI_INTERVAL>
+class GenericWifiPollingPolicy : public WifiPollingPolicy {
+ public:
+ GenericWifiPollingPolicy() : polling_interval_(DEFAULT_INTERVAL) {}
+ // WifiPollingPolicy
+ virtual void UpdatePollingInterval(bool scan_results_differ) {
+ if (scan_results_differ) {
+ polling_interval_ = DEFAULT_INTERVAL;
+ } else if (polling_interval_ == DEFAULT_INTERVAL) {
+ polling_interval_ = NO_CHANGE_INTERVAL;
+ } else {
+ DCHECK(polling_interval_ == NO_CHANGE_INTERVAL ||
+ polling_interval_ == TWO_NO_CHANGE_INTERVAL);
+ polling_interval_ = TWO_NO_CHANGE_INTERVAL;
+ }
+ }
+ virtual int PollingInterval() { return polling_interval_; }
+ virtual int NoWifiInterval() { return NO_WIFI_INTERVAL; }
+
+ private:
+ int polling_interval_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GEOLOCATION_WIFI_POLLING_POLICY_H_
diff --git a/chromium/content/browser/gpu/compositor_util.cc b/chromium/content/browser/gpu/compositor_util.cc
index a0cf1e21a2b..16810e326f3 100644
--- a/chromium/content/browser/gpu/compositor_util.cc
+++ b/chromium/content/browser/gpu/compositor_util.cc
@@ -2,15 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/public/browser/compositor_util.h"
+#include "content/browser/gpu/compositor_util.h"
#include "base/command_line.h"
#include "base/metrics/field_trial.h"
+#include "build/build_config.h"
#include "content/public/browser/gpu_data_manager.h"
#include "content/public/common/content_constants.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 {
@@ -44,31 +51,22 @@ bool IsForceCompositingModeBlacklisted() {
} // namespace
bool IsThreadedCompositingEnabled() {
-#if defined(OS_WIN) && defined(USE_AURA)
- // We always want compositing on Aura Windows.
+#if defined(USE_AURA)
+ // We always want threaded compositing on Aura.
return true;
#endif
- if (!CanDoAcceleratedCompositing())
- return false;
-
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
// Command line switches take precedence over blacklist and field trials.
if (command_line.HasSwitch(switches::kDisableForceCompositingMode) ||
- command_line.HasSwitch(switches::kDisableThreadedCompositing))
+ command_line.HasSwitch(switches::kDisableThreadedCompositing)) {
return false;
-
-#if defined(OS_CHROMEOS)
- // We always want threaded compositing on ChromeOS unless it's explicitly
- // disabled above.
- return true;
-#endif
-
- if (command_line.HasSwitch(switches::kEnableThreadedCompositing))
+ } else if (command_line.HasSwitch(switches::kEnableThreadedCompositing)) {
return true;
+ }
- if (IsForceCompositingModeBlacklisted())
+ if (!CanDoAcceleratedCompositing() || IsForceCompositingModeBlacklisted())
return false;
base::FieldTrial* trial =
@@ -78,40 +76,68 @@ bool IsThreadedCompositingEnabled() {
}
bool IsForceCompositingModeEnabled() {
-#if defined(OS_WIN) && defined(USE_AURA)
- // We always want compositing on Aura Windows.
- return true;
-#endif
-
- if (!CanDoAcceleratedCompositing())
- return false;
+ // Force compositing mode is a subset of threaded compositing mode.
+ if (IsThreadedCompositingEnabled())
+ return true;
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
// Command line switches take precedence over blacklisting and field trials.
if (command_line.HasSwitch(switches::kDisableForceCompositingMode))
return false;
+ else if (command_line.HasSwitch(switches::kForceCompositingMode))
+ return true;
-#if defined(OS_CHROMEOS)
- // We always want compositing ChromeOS unless it's explicitly disabled above.
- return true;
+ 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;
#endif
- if (command_line.HasSwitch(switches::kForceCompositingMode))
- return true;
+ return false;
+}
- if (IsForceCompositingModeBlacklisted())
- return false;
+bool IsDelegatedRendererEnabled() {
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ bool enabled = false;
- base::FieldTrial* trial =
- base::FieldTrialList::Find(kGpuCompositingFieldTrialName);
+ // Flags override.
+ enabled |= command_line.HasSwitch(switches::kEnableDelegatedRenderer);
+ enabled &= !command_line.HasSwitch(switches::kDisableDelegatedRenderer);
- // Force compositing is enabled in both the force compositing
- // and threaded compositing mode field trials.
- return trial &&
- (trial->group_name() ==
- kGpuCompositingFieldTrialForceCompositingEnabledName ||
- trial->group_name() == kGpuCompositingFieldTrialThreadEnabledName);
+ // Needs compositing, and thread.
+ if (enabled &&
+ (!IsForceCompositingModeEnabled() || !IsThreadedCompositingEnabled())) {
+ enabled = false;
+ LOG(ERROR) << "Disabling delegated-rendering because it needs "
+ << "force-compositing-mode and threaded-compositing.";
+ }
+
+ return enabled;
+}
+
+bool IsDeadlineSchedulingEnabled() {
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+
+ // Default to disabled.
+ bool enabled = false;
+
+ // Flags override.
+ enabled |= command_line.HasSwitch(switches::kEnableDeadlineScheduling);
+ enabled &= !command_line.HasSwitch(switches::kDisableDeadlineScheduling);
+
+ return enabled;
}
} // namespace content
diff --git a/chromium/content/browser/gpu/compositor_util.h b/chromium/content/browser/gpu/compositor_util.h
new file mode 100644
index 00000000000..c1c6a4229b1
--- /dev/null
+++ b/chromium/content/browser/gpu/compositor_util.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_GPU_COMPOSITOR_UTIL_H_
+#define CONTENT_BROWSER_GPU_COMPOSITOR_UTIL_H_
+
+#include "content/common/content_export.h"
+
+namespace content {
+
+// Returns true if the threaded compositor is on (via flags or field trial).
+CONTENT_EXPORT bool IsThreadedCompositingEnabled();
+
+// Returns true if force-compositing-mode is on (via flags or field trial).
+CONTENT_EXPORT bool IsForceCompositingModeEnabled();
+
+// Returns true if delegated-renderer is on (via flags, or platform default).
+CONTENT_EXPORT bool IsDelegatedRendererEnabled();
+
+// Returns true if deadline scheduling is on (via flags, or platform default).
+CONTENT_EXPORT bool IsDeadlineSchedulingEnabled();
+
+} // 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
new file mode 100644
index 00000000000..75fc60e429f
--- /dev/null
+++ b/chromium/content/browser/gpu/compositor_util_browsertest.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/gpu/compositor_util.h"
+#include "content/test/content_browser_test.h"
+
+#if defined(OS_MACOSX)
+#include "base/mac/mac_util.h"
+#elif defined(OS_WIN)
+#include "base/win/windows_version.h"
+#endif
+
+namespace content {
+
+typedef ContentBrowserTest CompositorUtilTest;
+
+// Test that threaded compositing and FCM are in the expected mode on the bots
+// for all platforms.
+IN_PROC_BROWSER_TEST_F(CompositorUtilTest, CompositingModeAsExpected) {
+ enum CompositingMode {
+ DISABLED,
+ ENABLED,
+ THREADED,
+ } expected_mode = DISABLED;
+#if defined(OS_ANDROID) || defined(USE_AURA)
+ expected_mode = THREADED;
+#elif defined(OS_MACOSX)
+ if (base::mac::IsOSMountainLionOrLater())
+ expected_mode = ENABLED;
+#elif defined(OS_WIN)
+ if (base::win::GetVersion() >= base::win::VERSION_VISTA)
+ expected_mode = ENABLED;
+#endif
+
+ EXPECT_EQ(expected_mode == ENABLED || expected_mode == THREADED,
+ IsForceCompositingModeEnabled());
+ EXPECT_EQ(expected_mode == THREADED, IsThreadedCompositingEnabled());
+}
+
+}
diff --git a/chromium/content/browser/gpu/gpu_crash_browsertest.cc b/chromium/content/browser/gpu/gpu_crash_browsertest.cc
index eafbc689cd0..98650d320c1 100644
--- a/chromium/content/browser/gpu/gpu_crash_browsertest.cc
+++ b/chromium/content/browser/gpu/gpu_crash_browsertest.cc
@@ -10,7 +10,7 @@
#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/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl.cc b/chromium/content/browser/gpu/gpu_data_manager_impl.cc
index 747503cedfe..31096574f9e 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl.cc
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl.cc
@@ -29,6 +29,11 @@ bool GpuDataManagerImpl::IsFeatureBlacklisted(int feature) const {
return private_->IsFeatureBlacklisted(feature);
}
+bool GpuDataManagerImpl::IsDriverBugWorkaroundActive(int feature) const {
+ base::AutoLock auto_lock(lock_);
+ return private_->IsDriverBugWorkaroundActive(feature);
+}
+
gpu::GPUInfo GpuDataManagerImpl::GetGPUInfo() const {
base::AutoLock auto_lock(lock_);
return private_->GetGPUInfo();
@@ -112,6 +117,11 @@ void GpuDataManagerImpl::DisableHardwareAcceleration() {
private_->DisableHardwareAcceleration();
}
+bool GpuDataManagerImpl::CanUseGpuBrowserCompositor() const {
+ base::AutoLock auto_lock(lock_);
+ return private_->CanUseGpuBrowserCompositor();
+}
+
void GpuDataManagerImpl::Initialize() {
base::AutoLock auto_lock(lock_);
private_->Initialize();
@@ -208,11 +218,6 @@ bool GpuDataManagerImpl::IsUsingAcceleratedSurface() const {
}
#endif
-bool GpuDataManagerImpl::CanUseGpuBrowserCompositor() const {
- base::AutoLock auto_lock(lock_);
- return private_->CanUseGpuBrowserCompositor();
-}
-
void GpuDataManagerImpl::BlockDomainFrom3DAPIs(
const GURL& url, DomainGuilt guilt) {
base::AutoLock auto_lock(lock_);
diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl.h b/chromium/content/browser/gpu/gpu_data_manager_impl.h
index 497d3bdf40b..a1ea2013129 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl.h
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl.h
@@ -80,6 +80,7 @@ class CONTENT_EXPORT GpuDataManagerImpl
std::string* gl_renderer,
std::string* gl_version) OVERRIDE;
virtual void DisableHardwareAcceleration() OVERRIDE;
+ virtual bool CanUseGpuBrowserCompositor() const OVERRIDE;
// This collects preliminary GPU info, load GpuBlacklist, and compute the
// preliminary blacklisted features; it should only be called at browser
@@ -141,8 +142,6 @@ class CONTENT_EXPORT GpuDataManagerImpl
bool IsUsingAcceleratedSurface() const;
#endif
- bool CanUseGpuBrowserCompositor() const;
-
// Maintenance of domains requiring explicit user permission before
// using client-facing 3D APIs (WebGL, Pepper 3D), either because
// the domain has caused the GPU to reset, or because too many GPU
@@ -177,6 +176,8 @@ class CONTENT_EXPORT GpuDataManagerImpl
// Called when GPU process initialization failed.
void OnGpuProcessInitFailure();
+ bool IsDriverBugWorkaroundActive(int feature) const;
+
private:
friend class GpuDataManagerImplPrivate;
friend class GpuDataManagerImplPrivateTest;
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 654048847ec..94adacd798a 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -42,7 +42,6 @@
#include "base/win/windows_version.h"
#endif // OS_WIN
#if defined(OS_ANDROID)
-#include "base/android/build_info.h"
#include "ui/gfx/android/device_display_info.h"
#endif // OS_ANDROID
@@ -230,7 +229,7 @@ std::string IntSetToString(const std::set<int>& list) {
void DisplayReconfigCallback(CGDirectDisplayID display,
CGDisplayChangeSummaryFlags flags,
void* gpu_data_manager) {
- if(flags == kCGDisplayBeginConfigurationFlag)
+ if (flags == kCGDisplayBeginConfigurationFlag)
return; // This call contains no information about the display change
GpuDataManagerImpl* manager =
@@ -259,36 +258,11 @@ 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_arm =
- gpu_info.gl_vendor.find("ARM") != std::string::npos;
- bool is_qualcomm =
- gpu_info.gl_vendor.find("Qualcomm") != std::string::npos;
- bool is_broadcom =
- gpu_info.gl_vendor.find("Broadcom") != std::string::npos;
- bool is_mali_t604 = is_arm &&
- gpu_info.gl_renderer.find("Mali-T604") != std::string::npos;
- bool is_nvidia =
- gpu_info.gl_vendor.find("NVIDIA") != std::string::npos;
-
- bool is_vivante =
- gpu_info.gl_extensions.find("GL_VIV_shader_binary") !=
- 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;
- int sdk_int = base::android::BuildInfo::GetInstance()->sdk_int();
-
- // IMG: avoid context switching perf problems, crashes with share groups
- // Mali-T604: http://crbug.com/154715
- // QualComm, NVIDIA: Crashes with share groups
- if (is_vivante || is_img || is_mali_t604 || (is_nvidia && (sdk_int < 18)) ||
- is_qualcomm || is_broadcom) {
- command_line->AppendSwitch(switches::kEnableVirtualGLContexts);
- }
-
gfx::DeviceDisplayInfo info;
int default_tile_size = 256;
@@ -311,7 +285,7 @@ void ApplyAndroidWorkarounds(const gpu::GPUInfo& gpu_info,
// 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::kUseMapImage))
+ if (command_line->HasSwitch(cc::switches::kEnableMapImage))
default_tile_size *= 2;
// Set the command line if it isn't already set and we changed
@@ -362,6 +336,13 @@ void GpuDataManagerImplPrivate::InitializeForTesting(
}
bool GpuDataManagerImplPrivate::IsFeatureBlacklisted(int feature) const {
+#if defined(OS_CHROMEOS)
+ if (feature == gpu::GPU_FEATURE_TYPE_PANEL_FITTING &&
+ CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisablePanelFitting)) {
+ return true;
+ }
+#endif // OS_CHROMEOS
if (use_swiftshader_) {
// Skia's software rendering is probably more efficient than going through
// software emulation of the GPU, so use that.
@@ -373,6 +354,10 @@ bool GpuDataManagerImplPrivate::IsFeatureBlacklisted(int feature) const {
return (blacklisted_features_.count(feature) == 1);
}
+bool GpuDataManagerImplPrivate::IsDriverBugWorkaroundActive(int feature) const {
+ return (gpu_driver_bugs_.count(feature) == 1);
+}
+
size_t GpuDataManagerImplPrivate::GetBlacklistedFeatureCount() const {
if (use_swiftshader_)
return 1;
@@ -740,6 +725,11 @@ void GpuDataManagerImplPrivate::AppendGpuCommandLine(
IntSetToString(gpu_driver_bugs_));
}
+ if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE) &&
+ !command_line->HasSwitch(switches::kDisableAcceleratedVideoDecode)) {
+ command_line->AppendSwitch(switches::kDisableAcceleratedVideoDecode);
+ }
+
#if defined(OS_WIN)
// DisplayLink 7.1 and earlier can cause the GPU process to crash on startup.
// http://crbug.com/177611
@@ -809,8 +799,9 @@ void GpuDataManagerImplPrivate::UpdateRendererWebPrefs(
prefs->flash_stage3d_baseline_enabled = false;
if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS))
prefs->accelerated_2d_canvas_enabled = false;
- if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_MULTISAMPLING)
- || display_count_ > 1)
+ if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_MULTISAMPLING) ||
+ (IsDriverBugWorkaroundActive(gpu::DISABLE_MULTIMONITOR_MULTISAMPLING) &&
+ display_count_ > 1))
prefs->gl_multisampling_enabled = false;
if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_3D_CSS)) {
prefs->accelerated_compositing_for_3d_transforms_enabled = false;
@@ -833,6 +824,7 @@ void GpuDataManagerImplPrivate::UpdateRendererWebPrefs(
prefs->accelerated_compositing_enabled = true;
prefs->accelerated_compositing_for_3d_transforms_enabled = true;
prefs->accelerated_compositing_for_plugins_enabled = true;
+ prefs->accelerated_compositing_for_video_enabled = true;
}
#if defined(USE_AURA)
@@ -1040,21 +1032,24 @@ void GpuDataManagerImplPrivate::InitializeImpl(
if (!gpu_blacklist_json.empty()) {
gpu_blacklist_.reset(gpu::GpuBlacklist::Create());
- gpu_blacklist_->LoadList(
+ 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());
- gpu_switching_list_->LoadList(
+ bool success = gpu_switching_list_->LoadList(
browser_version_string, gpu_switching_list_json,
gpu::GpuControlList::kCurrentOsOnly);
+ DCHECK(success);
}
if (!gpu_driver_bug_list_json.empty()) {
gpu_driver_bug_list_.reset(gpu::GpuDriverBugList::Create());
- gpu_driver_bug_list_->LoadList(
+ bool success = gpu_driver_bug_list_->LoadList(
browser_version_string, gpu_driver_bug_list_json,
gpu::GpuControlList::kCurrentOsOnly);
+ DCHECK(success);
}
gpu_info_ = gpu_info;
@@ -1250,4 +1245,3 @@ void GpuDataManagerImplPrivate::OnGpuProcessInitFailure() {
}
} // namespace content
-
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 eb226e863dc..8d15296e4a9 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl_private.h
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl_private.h
@@ -28,6 +28,7 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
const std::string& gpu_blacklist_json,
const gpu::GPUInfo& gpu_info);
bool IsFeatureBlacklisted(int feature) const;
+ bool IsDriverBugWorkaroundActive(int feature) const;
gpu::GPUInfo GetGPUInfo() const;
void GetGpuProcessHandles(
const GpuDataManager::GetGpuProcessHandlesCallback& callback) const;
diff --git a/chromium/content/browser/gpu/gpu_functional_browsertest.cc b/chromium/content/browser/gpu/gpu_functional_browsertest.cc
index b3c2a57319f..4e95d2d5c11 100644
--- a/chromium/content/browser/gpu/gpu_functional_browsertest.cc
+++ b/chromium/content/browser/gpu/gpu_functional_browsertest.cc
@@ -10,7 +10,7 @@
#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/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
@@ -70,7 +70,6 @@ class GpuFunctionalTest : public ContentBrowserTest {
}
void VerifyGPUProcessOnPage(std::string filename, bool wait) {
- Shell::Initialize();
ASSERT_TRUE(test_server()->Start());
DOMMessageQueue message_queue;
diff --git a/chromium/content/browser/gpu/gpu_internals_ui.cc b/chromium/content/browser/gpu/gpu_internals_ui.cc
index 0e778c277b9..0340077147d 100644
--- a/chromium/content/browser/gpu/gpu_internals_ui.cc
+++ b/chromium/content/browser/gpu/gpu_internals_ui.cc
@@ -15,9 +15,9 @@
#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"
-#include "content/public/browser/compositor_util.h"
#include "content/public/browser/gpu_data_manager_observer.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
diff --git a/chromium/content/browser/gpu/gpu_memory_test.cc b/chromium/content/browser/gpu/gpu_memory_test.cc
index cb74a629299..7f9a3fee167 100644
--- a/chromium/content/browser/gpu/gpu_memory_test.cc
+++ b/chromium/content/browser/gpu/gpu_memory_test.cc
@@ -12,7 +12,7 @@
#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/shell.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"
@@ -76,7 +76,6 @@ class GpuMemoryTest : public ContentBrowserTest {
virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
command_line->AppendSwitch(switches::kEnableLogging);
- command_line->AppendSwitch(switches::kForceCompositingMode);
command_line->AppendSwitchASCII(switches::kForceGpuMemAvailableMb,
kMemoryLimitMBSwitch);
// Only run this on GPU bots for now. These tests should work with
@@ -217,15 +216,18 @@ class GpuMemoryTest : public ContentBrowserTest {
#if defined(OS_LINUX) && !defined(NDEBUG)
// http://crbug.com/254724
-#define IF_NOT_DEBUG_LINUX(x) DISABLED_ ## x
+#define MAYBE(x) DISABLED_ ## x
+#elif defined(OS_WIN) && defined(USE_AURA)
+// http://crbug.com/292882
+#define MAYBE(x) DISABLED_ ## x
#else
-#define IF_NOT_DEBUG_LINUX(x) x
+#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,
- IF_NOT_DEBUG_LINUX(SingleWindowDoesNotExceedLimit)) {
+ MAYBE(SingleWindowDoesNotExceedLimit)) {
if (!AllowTestsToRun())
return;
diff --git a/chromium/content/browser/gpu/gpu_pixel_browsertest.cc b/chromium/content/browser/gpu/gpu_pixel_browsertest.cc
index 5909321377f..d6b55e2c7ee 100644
--- a/chromium/content/browser/gpu/gpu_pixel_browsertest.cc
+++ b/chromium/content/browser/gpu/gpu_pixel_browsertest.cc
@@ -16,7 +16,7 @@
#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/shell.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"
@@ -59,7 +59,7 @@ bool ReadPNGFile(const base::FilePath& file_path, SkBitmap* bitmap) {
return false;
std::string png_data;
- return file_util::ReadFileToString(abs_path, &png_data) &&
+ return base::ReadFileToString(abs_path, &png_data) &&
gfx::PNGCodec::Decode(reinterpret_cast<unsigned char*>(&png_data[0]),
png_data.length(),
bitmap);
@@ -461,7 +461,7 @@ IN_PROC_BROWSER_TEST_F(GpuPixelBrowserTest, MANUAL_WebGLGreenTriangle) {
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 = 209827;
+ const int64 ref_img_revision_update = 223891;
const ReferencePixel ref_pixels[] = {
// x, y, r, g, b
@@ -484,7 +484,7 @@ IN_PROC_BROWSER_TEST_F(GpuPixelBrowserTest, MANUAL_CSS3DBlueBox) {
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 = 123489;
+ const int64 ref_img_revision_update = 224170;
const ReferencePixel ref_pixels[] = {
// x, y, r, g, b
@@ -513,7 +513,7 @@ class GpuPixelTestCanvas2DSD : public GpuPixelBrowserTest {
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 = 123489;
+ const int64 ref_img_revision_update = 224170;
const ReferencePixel ref_pixels[] = {
// x, y, r, g, b
diff --git a/chromium/content/browser/gpu/gpu_process_host.cc b/chromium/content/browser/gpu/gpu_process_host.cc
index 8cbb7aa1d82..0482b347e85 100644
--- a/chromium/content/browser/gpu/gpu_process_host.cc
+++ b/chromium/content/browser/gpu/gpu_process_host.cc
@@ -6,8 +6,9 @@
#include "base/base64.h"
#include "base/base_switches.h"
+#include "base/basictypes.h"
#include "base/bind.h"
-#include "base/bind_helpers.h"
+#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/logging.h"
@@ -24,8 +25,6 @@
#include "content/common/child_process_host_impl.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/common/view_messages.h"
-#include "content/gpu/gpu_child_thread.h"
-#include "content/gpu/gpu_process.h"
#include "content/port/browser/render_widget_host_view_frame_subscriber.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
@@ -37,7 +36,7 @@
#include "gpu/command_buffer/service/gpu_switches.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_switches.h"
-#include "ui/base/latency_info.h"
+#include "ui/events/latency_info.h"
#include "ui/gl/gl_switches.h"
@@ -81,9 +80,12 @@ void SendGpuProcessMessage(GpuProcessHost::GpuProcessKind kind,
}
}
-void AcceleratedSurfaceBuffersSwappedCompletedForGPU(int host_id,
- int route_id,
- bool alive) {
+void AcceleratedSurfaceBuffersSwappedCompletedForGPU(
+ int host_id,
+ int route_id,
+ bool alive,
+ base::TimeTicks vsync_timebase,
+ base::TimeDelta vsync_interval) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO,
@@ -91,7 +93,9 @@ void AcceleratedSurfaceBuffersSwappedCompletedForGPU(int host_id,
base::Bind(&AcceleratedSurfaceBuffersSwappedCompletedForGPU,
host_id,
route_id,
- alive));
+ alive,
+ vsync_timebase,
+ vsync_interval));
return;
}
@@ -100,6 +104,10 @@ void AcceleratedSurfaceBuffersSwappedCompletedForGPU(int host_id,
if (alive) {
AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
ack_params.sync_point = 0;
+#if defined(OS_WIN)
+ ack_params.vsync_timebase = vsync_timebase;
+ ack_params.vsync_interval = vsync_interval;
+#endif
host->Send(
new AcceleratedSurfaceMsg_BufferPresented(route_id, ack_params));
} else {
@@ -151,10 +159,10 @@ void AcceleratedSurfaceBuffersSwappedCompleted(
base::TimeTicks timebase,
base::TimeDelta interval,
const ui::LatencyInfo& latency_info) {
- AcceleratedSurfaceBuffersSwappedCompletedForGPU(host_id, route_id,
- alive);
- AcceleratedSurfaceBuffersSwappedCompletedForRenderer(surface_id, timebase,
- interval, latency_info);
+ AcceleratedSurfaceBuffersSwappedCompletedForGPU(
+ host_id, route_id, alive, timebase, interval);
+ AcceleratedSurfaceBuffersSwappedCompletedForRenderer(
+ surface_id, timebase, interval, latency_info);
}
// NOTE: changes to this class need to be reviewed by the security team.
@@ -278,43 +286,6 @@ class GpuSandboxedProcessLauncherDelegate
} // anonymous namespace
-// Single process not supported in multiple dll mode currently.
-#if !defined(CHROME_MULTIPLE_DLL)
-// This class creates a GPU thread (instead of a GPU process), when running
-// with --in-process-gpu or --single-process.
-class GpuMainThread : public base::Thread {
- public:
- explicit GpuMainThread(const std::string& channel_id)
- : base::Thread("Chrome_InProcGpuThread"),
- channel_id_(channel_id),
- gpu_process_(NULL) {
- }
-
- virtual ~GpuMainThread() {
- Stop();
- }
-
- protected:
- virtual void Init() OVERRIDE {
- gpu_process_ = new GpuProcess();
- // The process object takes ownership of the thread object, so do not
- // save and delete the pointer.
- gpu_process_->set_main_thread(new GpuChildThread(channel_id_));
- }
-
- virtual void CleanUp() OVERRIDE {
- delete gpu_process_;
- }
-
- private:
- std::string channel_id_;
- // Deleted in CleanUp() on the gpu thread, so don't use smart pointers.
- GpuProcess* gpu_process_;
-
- DISALLOW_COPY_AND_ASSIGN(GpuMainThread);
-};
-#endif // !CHROME_MULTIPLE_DLL
-
// static
bool GpuProcessHost::ValidateHost(GpuProcessHost* host) {
if (!host)
@@ -401,6 +372,13 @@ void GpuProcessHost::SendOnIO(GpuProcessKind kind,
}
}
+GpuMainThreadFactoryFunction g_gpu_main_thread_factory = NULL;
+
+void GpuProcessHost::RegisterGpuMainThreadFactory(
+ GpuMainThreadFactoryFunction create) {
+ g_gpu_main_thread_factory = create;
+}
+
// static
GpuProcessHost* GpuProcessHost::FromID(int host_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
@@ -550,7 +528,8 @@ GpuProcessHost::~GpuProcessHost() {
std::string message;
if (!in_process_) {
int exit_code;
- base::TerminationStatus status = process_->GetTerminationStatus(&exit_code);
+ base::TerminationStatus status = process_->GetTerminationStatus(
+ false /* known_dead */, &exit_code);
UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessTerminationStatus",
status,
base::TERMINATION_STATUS_MAX_ENUM);
@@ -598,19 +577,15 @@ bool GpuProcessHost::Init() {
if (channel_id.empty())
return false;
- // Single process not supported in multiple dll mode currently.
-#if !defined(CHROME_MULTIPLE_DLL)
- if (in_process_) {
+ if (in_process_ && g_gpu_main_thread_factory) {
CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kDisableGpuWatchdog);
- in_process_gpu_thread_.reset(new GpuMainThread(channel_id));
+ in_process_gpu_thread_.reset(g_gpu_main_thread_factory(channel_id));
in_process_gpu_thread_->Start();
OnProcessLaunched(); // Fake a callback that the process is ready.
- } else
-#endif // !CHROME_MULTIPLE_DLL
- if (!LaunchGpuProcess(channel_id)) {
+ } else if (!LaunchGpuProcess(channel_id)) {
return false;
}
@@ -916,7 +891,7 @@ void GpuProcessHost::OnAcceleratedSurfaceBuffersSwapped(
base::ScopedClosureRunner scoped_completion_runner(
base::Bind(&AcceleratedSurfaceBuffersSwappedCompletedForGPU,
host_id_, params.route_id,
- true /* alive */));
+ true /* alive */, base::TimeTicks(), base::TimeDelta()));
int render_process_id = 0;
int render_widget_id = 0;
@@ -933,7 +908,7 @@ void GpuProcessHost::OnAcceleratedSurfaceBuffersSwapped(
// if the browser is waiting for a new frame. Otherwise the RenderWidgetHelper
// will forward to the RenderWidgetHostView via RenderProcessHostImpl and
// RenderWidgetHostImpl.
- scoped_completion_runner.Release();
+ ignore_result(scoped_completion_runner.Release());
ViewHostMsg_CompositorSurfaceBuffersSwapped_Params view_params;
view_params.surface_id = params.surface_id;
@@ -969,7 +944,7 @@ void GpuProcessHost::OnAcceleratedSurfaceBuffersSwapped(
TRACE_EVENT1("gpu", "SurfaceIDNotFound_RoutingToUI",
"surface_id", params.surface_id);
// This is a content area swap, send it on to the UI thread.
- scoped_completion_runner.Release();
+ ignore_result(scoped_completion_runner.Release());
RouteOnUIThread(GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params));
return;
}
@@ -983,7 +958,7 @@ void GpuProcessHost::OnAcceleratedSurfaceBuffersSwapped(
"EarlyOut_NativeWindowNotFound",
"handle",
handle.handle);
- scoped_completion_runner.Release();
+ ignore_result(scoped_completion_runner.Release());
AcceleratedSurfaceBuffersSwappedCompleted(host_id_,
params.route_id,
params.surface_id,
@@ -994,7 +969,7 @@ void GpuProcessHost::OnAcceleratedSurfaceBuffersSwapped(
return;
}
- scoped_completion_runner.Release();
+ ignore_result(scoped_completion_runner.Release());
presenter->AsyncPresentAndAcknowledge(
params.size,
params.surface_handle,
@@ -1079,7 +1054,7 @@ void GpuProcessHost::OnProcessLaunched() {
void GpuProcessHost::OnProcessCrashed(int exit_code) {
SendOutstandingReplies();
GpuDataManagerImpl::GetInstance()->ProcessCrashed(
- process_->GetTerminationStatus(NULL));
+ process_->GetTerminationStatus(true /* known_dead */, NULL));
}
GpuProcessHost::GpuProcessKind GpuProcessHost::kind() {
@@ -1148,7 +1123,6 @@ bool GpuProcessHost::LaunchGpuProcess(const std::string& channel_id) {
switches::kDisableSeccompFilterSandbox,
switches::kEnableLogging,
switches::kEnableShareGroupAsyncTextureUpload,
- switches::kEnableVirtualGLContexts,
switches::kGpuStartupDialog,
switches::kGpuSandboxAllowSysVShm,
switches::kLoggingLevel,
@@ -1195,7 +1169,7 @@ bool GpuProcessHost::LaunchGpuProcess(const std::string& channel_id) {
new GpuSandboxedProcessLauncherDelegate(cmd_line),
#elif defined(OS_POSIX)
false,
- base::EnvironmentVector(),
+ base::EnvironmentMap(),
#endif
cmd_line);
process_launched_ = true;
diff --git a/chromium/content/browser/gpu/gpu_process_host.h b/chromium/content/browser/gpu/gpu_process_host.h
index 8908a1035db..32345b72800 100644
--- a/chromium/content/browser/gpu/gpu_process_host.h
+++ b/chromium/content/browser/gpu/gpu_process_host.h
@@ -44,6 +44,8 @@ class GpuMainThread;
class RenderWidgetHostViewFrameSubscriber;
class ShaderDiskCache;
+typedef base::Thread* (*GpuMainThreadFactoryFunction)(const std::string& id);
+
class GpuProcessHost : public BrowserChildProcessHostDelegate,
public IPC::Sender,
public base::NonThreadSafe {
@@ -82,6 +84,9 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
CauseForGpuLaunch cause,
IPC::Message* message);
+ CONTENT_EXPORT static void RegisterGpuMainThreadFactory(
+ GpuMainThreadFactoryFunction create);
+
// Get the GPU process host for the GPU process with the given ID. Returns
// null if the process no longer exists.
static GpuProcessHost* FromID(int host_id);
@@ -214,9 +219,7 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
bool swiftshader_rendering_;
GpuProcessKind kind_;
-#if !defined(CHROME_MULTIPLE_DLL)
- scoped_ptr<GpuMainThread> in_process_gpu_thread_;
-#endif
+ scoped_ptr<base::Thread> in_process_gpu_thread_;
// Whether we actually launched a GPU process.
bool process_launched_;
diff --git a/chromium/content/browser/gpu/webgl_conformance_test.cc b/chromium/content/browser/gpu/webgl_conformance_test.cc
index 79f30782830..e8fb8a59b92 100644
--- a/chromium/content/browser/gpu/webgl_conformance_test.cc
+++ b/chromium/content/browser/gpu/webgl_conformance_test.cc
@@ -10,7 +10,7 @@
#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/shell.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"
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 58369110014..70b3b52105b 100644
--- a/chromium/content/browser/indexed_db/indexed_db_backing_store.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -348,11 +348,10 @@ WARN_UNUSED_RESULT static bool GetMaxObjectStoreId(
class DefaultLevelDBFactory : public LevelDBFactory {
public:
- virtual leveldb::Status OpenLevelDB(
- const base::FilePath& file_name,
- const LevelDBComparator* comparator,
- scoped_ptr<LevelDBDatabase>* db,
- bool* is_disk_full) OVERRIDE {
+ virtual leveldb::Status OpenLevelDB(const base::FilePath& file_name,
+ const LevelDBComparator* comparator,
+ scoped_ptr<LevelDBDatabase>* db,
+ bool* is_disk_full) OVERRIDE {
return LevelDBDatabase::Open(file_name, comparator, db, is_disk_full);
}
virtual bool DestroyLevelDB(const base::FilePath& file_name) OVERRIDE {
@@ -406,6 +405,7 @@ enum IndexedDBLevelDBBackingStoreOpenResult {
INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX,
};
+// TODO(dgrogan): Move to leveldb_env.
bool RecoveryCouldBeFruitful(leveldb::Status status) {
leveldb_env::MethodID method;
int error = -1;
@@ -445,13 +445,15 @@ 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) {
+ WebKit::WebIDBCallbacks::DataLoss* data_loss,
+ bool* disk_full) {
*data_loss = WebKit::WebIDBCallbacks::DataLossNone;
DefaultLevelDBFactory leveldb_factory;
return IndexedDBBackingStore::Open(origin_identifier,
path_base,
file_identifier,
data_loss,
+ disk_full,
&leveldb_factory);
}
@@ -460,10 +462,12 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
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());
@@ -529,10 +533,14 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
base::FilePath file_path = path_base.Append(identifier_path);
- bool is_disk_full = false;
scoped_ptr<LevelDBDatabase> db;
leveldb::Status status = leveldb_factory->OpenLevelDB(
- file_path, comparator.get(), &db, &is_disk_full);
+ file_path, comparator.get(), &db, is_disk_full);
+
+ if (!status.ok() && leveldb_env::IndicatesDiskFull(status)) {
+ DCHECK(!db);
+ *is_disk_full = true;
+ }
if (db) {
bool known = false;
@@ -569,24 +577,24 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX + 1,
base::HistogramBase::kUmaTargetedHistogramFlag)
->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_SUCCESS);
- } else if (is_disk_full) {
- LOG(ERROR) << "Unable to open backing store - disk is full.";
+ } else if (!RecoveryCouldBeFruitful(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_DISK_FULL);
+ ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_NO_RECOVERY);
return scoped_refptr<IndexedDBBackingStore>();
- } else if (!RecoveryCouldBeFruitful(status)) {
- LOG(ERROR) << "Unable to open backing store, not trying to recover - "
- << status.ToString();
+ } 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_NO_RECOVERY);
+ ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_DISK_FULL);
return scoped_refptr<IndexedDBBackingStore>();
} else {
LOG(ERROR) << "IndexedDB backing store open failed, attempting cleanup";
@@ -968,10 +976,10 @@ bool IndexedDBBackingStore::GetObjectStores(
it->Next();
if (!CheckObjectStoreAndMetaDataType(
- it.get(),
- stop_key,
- object_store_id,
- ObjectStoreMetaDataKey::AUTO_INCREMENT)) {
+ it.get(),
+ stop_key,
+ object_store_id,
+ ObjectStoreMetaDataKey::AUTO_INCREMENT)) {
INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES);
break;
}
@@ -993,20 +1001,20 @@ bool IndexedDBBackingStore::GetObjectStores(
it->Next(); // Last version.
if (!CheckObjectStoreAndMetaDataType(
- it.get(),
- stop_key,
- object_store_id,
- ObjectStoreMetaDataKey::LAST_VERSION)) {
+ it.get(),
+ stop_key,
+ object_store_id,
+ ObjectStoreMetaDataKey::LAST_VERSION)) {
INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES);
break;
}
it->Next(); // Maximum index id allocated.
if (!CheckObjectStoreAndMetaDataType(
- it.get(),
- stop_key,
- object_store_id,
- ObjectStoreMetaDataKey::MAX_INDEX_ID)) {
+ it.get(),
+ stop_key,
+ object_store_id,
+ ObjectStoreMetaDataKey::MAX_INDEX_ID)) {
INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES);
break;
}
@@ -1542,7 +1550,7 @@ bool IndexedDBBackingStore::GetIndexes(
it->Next(); // unique flag
if (!CheckIndexAndMetaDataKey(
- it.get(), stop_key, index_id, IndexMetaDataKey::UNIQUE)) {
+ it.get(), stop_key, index_id, IndexMetaDataKey::UNIQUE)) {
INTERNAL_CONSISTENCY_ERROR(GET_INDEXES);
break;
}
@@ -1555,7 +1563,7 @@ bool IndexedDBBackingStore::GetIndexes(
it->Next(); // key_path
if (!CheckIndexAndMetaDataKey(
- it.get(), stop_key, index_id, IndexMetaDataKey::KEY_PATH)) {
+ it.get(), stop_key, index_id, IndexMetaDataKey::KEY_PATH)) {
INTERNAL_CONSISTENCY_ERROR(GET_INDEXES);
break;
}
@@ -1623,7 +1631,7 @@ bool IndexedDBBackingStore::CreateIndex(
LevelDBTransaction* leveldb_transaction =
IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
if (!SetMaxIndexId(
- leveldb_transaction, database_id, object_store_id, index_id))
+ leveldb_transaction, database_id, object_store_id, index_id))
return false;
const std::string name_key = IndexMetaDataKey::Encode(
@@ -2402,8 +2410,9 @@ bool ObjectStoreCursorOptions(
cursor_options->high_open = true; // Not included.
} else {
// We need a key that exists.
- if (!FindGreatestKeyLessThanOrEqual(
- transaction, cursor_options->high_key, &cursor_options->high_key))
+ if (!FindGreatestKeyLessThanOrEqual(transaction,
+ cursor_options->high_key,
+ &cursor_options->high_key))
return false;
cursor_options->high_open = false;
}
@@ -2416,7 +2425,7 @@ bool ObjectStoreCursorOptions(
// For reverse cursors, we need a key that exists.
std::string found_high_key;
if (!FindGreatestKeyLessThanOrEqual(
- transaction, cursor_options->high_key, &found_high_key))
+ transaction, cursor_options->high_key, &found_high_key))
return false;
// If the target key should not be included, but we end up with a smaller
@@ -2472,8 +2481,9 @@ bool IndexCursorOptions(
cursor_options->high_open = false; // Included.
if (!cursor_options->forward) { // We need a key that exists.
- if (!FindGreatestKeyLessThanOrEqual(
- transaction, cursor_options->high_key, &cursor_options->high_key))
+ if (!FindGreatestKeyLessThanOrEqual(transaction,
+ cursor_options->high_key,
+ &cursor_options->high_key))
return false;
cursor_options->high_open = false;
}
@@ -2485,7 +2495,7 @@ bool IndexCursorOptions(
std::string found_high_key;
// Seek to the *last* key in the set of non-unique keys
if (!FindGreatestKeyLessThanOrEqual(
- transaction, cursor_options->high_key, &found_high_key))
+ transaction, cursor_options->high_key, &found_high_key))
return false;
// If the target key should not be included, but we end up with a smaller
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 4498b0875a4..3948411de24 100644
--- a/chromium/content/browser/indexed_db/indexed_db_backing_store.h
+++ b/chromium/content/browser/indexed_db/indexed_db_backing_store.h
@@ -22,6 +22,7 @@
#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"
namespace content {
@@ -48,13 +49,15 @@ class CONTENT_EXPORT IndexedDBBackingStore
const std::string& origin_identifier,
const base::FilePath& path_base,
const std::string& file_identifier,
- WebKit::WebIDBCallbacks::DataLoss* data_loss);
+ WebKit::WebIDBCallbacks::DataLoss* data_loss,
+ bool* disk_full);
static scoped_refptr<IndexedDBBackingStore> Open(
const std::string& origin_identifier,
const base::FilePath& path_base,
const std::string& file_identifier,
WebKit::WebIDBCallbacks::DataLoss* data_loss,
+ bool* disk_full,
LevelDBFactory* factory);
static scoped_refptr<IndexedDBBackingStore> OpenInMemory(
const std::string& file_identifier);
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 cc6ea1f2a64..50fb2f07a5d 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
@@ -12,6 +12,7 @@
#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"
@@ -325,10 +326,12 @@ class MockIDBFactory : public IndexedDBFactory {
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);
+ &data_loss,
+ &disk_full);
EXPECT_EQ(WebKit::WebIDBCallbacks::DataLossNone, data_loss);
return backing_store;
}
@@ -413,6 +416,50 @@ TEST(IndexedDBFactoryTest, RejectLongOrigins) {
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 ab010cbd92a..fb6d0cd2795 100644
--- a/chromium/content/browser/indexed_db/indexed_db_browsertest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_browsertest.cc
@@ -21,7 +21,7 @@
#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/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
#include "webkit/browser/database/database_util.h"
@@ -46,7 +46,8 @@ class IndexedDBBrowserTest : public ContentBrowserTest {
LOG(INFO) << "Navigating to URL and blocking.";
NavigateToURLBlockUntilNavigationsComplete(the_browser, test_url, 2);
LOG(INFO) << "Navigation done.";
- std::string result = the_browser->web_contents()->GetURL().ref();
+ std::string result =
+ the_browser->web_contents()->GetLastCommittedURL().ref();
if (result != "pass") {
std::string js_result;
ASSERT_TRUE(ExecuteScriptAndExtractString(
@@ -430,4 +431,16 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, ForceCloseEventTest) {
EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle());
}
+class IndexedDBBrowserTestSingleProcess : public IndexedDBBrowserTest {
+ public:
+ virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ command_line->AppendSwitch(switches::kSingleProcess);
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestSingleProcess,
+ RenderThreadShutdownTest) {
+ SimpleTest(GetTestUrl("indexeddb", "shutdown_with_requests.html"));
+}
+
} // namespace content
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 e05ceb91f57..6b60a4f9291 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
@@ -69,11 +69,13 @@ TEST(IndexedDBIOErrorTest, CleanUpTest) {
MockLevelDBFactory mock_leveldb_factory;
WebKit::WebIDBCallbacks::DataLoss data_loss =
WebKit::WebIDBCallbacks::DataLossNone;
+ bool disk_full = false;
scoped_refptr<IndexedDBBackingStore> backing_store =
IndexedDBBackingStore::Open(origin_identifier,
path,
dummy_file_identifier,
&data_loss,
+ &disk_full,
&mock_leveldb_factory);
}
@@ -115,6 +117,7 @@ TEST(IndexedDBNonRecoverableIOErrorTest, NuancedCleanupTest) {
std::string dummy_file_identifier;
WebKit::WebIDBCallbacks::DataLoss data_loss =
WebKit::WebIDBCallbacks::DataLossNone;
+ bool disk_full = false;
MockErrorLevelDBFactory<int> mock_leveldb_factory(ENOSPC, false);
scoped_refptr<IndexedDBBackingStore> backing_store =
@@ -122,6 +125,7 @@ TEST(IndexedDBNonRecoverableIOErrorTest, NuancedCleanupTest) {
path,
dummy_file_identifier,
&data_loss,
+ &disk_full,
&mock_leveldb_factory);
MockErrorLevelDBFactory<base::PlatformFileError> mock_leveldb_factory2(
@@ -131,6 +135,7 @@ TEST(IndexedDBNonRecoverableIOErrorTest, NuancedCleanupTest) {
path,
dummy_file_identifier,
&data_loss,
+ &disk_full,
&mock_leveldb_factory2);
MockErrorLevelDBFactory<int> mock_leveldb_factory3(EIO, true);
@@ -139,6 +144,7 @@ TEST(IndexedDBNonRecoverableIOErrorTest, NuancedCleanupTest) {
path,
dummy_file_identifier,
&data_loss,
+ &disk_full,
&mock_leveldb_factory3);
MockErrorLevelDBFactory<base::PlatformFileError> mock_leveldb_factory4(
@@ -148,6 +154,7 @@ TEST(IndexedDBNonRecoverableIOErrorTest, NuancedCleanupTest) {
path,
dummy_file_identifier,
&data_loss,
+ &disk_full,
&mock_leveldb_factory4);
}
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 38decc286f4..6c4dd84ed79 100644
--- a/chromium/content/browser/indexed_db/indexed_db_context_impl.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_context_impl.cc
@@ -15,10 +15,12 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_restrictions.h"
+#include "base/time/time.h"
#include "base/values.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/indexed_db/indexed_db_connection.h"
#include "content/browser/indexed_db/indexed_db_database.h"
+#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_transaction.h"
@@ -218,7 +220,41 @@ ListValue* IndexedDBContextImpl::GetAllOriginsDetails() {
const char* kModes[] = { "readonly", "readwrite", "versionchange" };
transaction_info->SetString("mode", kModes[transaction->mode()]);
- transaction_info->SetBoolean("running", transaction->IsRunning());
+ switch (transaction->queue_status()) {
+ case IndexedDBTransaction::CREATED:
+ transaction_info->SetString("status", "created");
+ break;
+ case IndexedDBTransaction::BLOCKED:
+ transaction_info->SetString("status", "blocked");
+ break;
+ case IndexedDBTransaction::UNBLOCKED:
+ if (transaction->IsRunning())
+ transaction_info->SetString("status", "running");
+ else
+ transaction_info->SetString("status", "started");
+ break;
+ }
+
+ transaction_info->SetDouble(
+ "pid",
+ IndexedDBDispatcherHost::TransactionIdToProcessId(
+ transaction->id()));
+ transaction_info->SetDouble(
+ "tid",
+ IndexedDBDispatcherHost::TransactionIdToRendererTransactionId(
+ transaction->id()));
+ transaction_info->SetDouble(
+ "age",
+ (base::Time::Now() - transaction->creation_time())
+ .InMillisecondsF());
+ transaction_info->SetDouble(
+ "runtime",
+ (base::Time::Now() - transaction->start_time())
+ .InMillisecondsF());
+ transaction_info->SetDouble("tasks_scheduled",
+ transaction->tasks_scheduled());
+ transaction_info->SetDouble("tasks_completed",
+ transaction->tasks_completed());
scoped_ptr<ListValue> scope(new ListValue());
for (std::set<int64>::const_iterator scope_it =
diff --git a/chromium/content/browser/indexed_db/indexed_db_cursor.cc b/chromium/content/browser/indexed_db/indexed_db_cursor.cc
index 1ee13e7c0b7..cb254d95908 100644
--- a/chromium/content/browser/indexed_db/indexed_db_cursor.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_cursor.cc
@@ -4,6 +4,7 @@
#include "content/browser/indexed_db/indexed_db_cursor.h"
+#include "base/bind.h"
#include "base/logging.h"
#include "content/browser/indexed_db/indexed_db_callbacks.h"
#include "content/browser/indexed_db/indexed_db_database_error.h"
@@ -12,53 +13,6 @@
namespace content {
-class IndexedDBCursor::CursorIterationOperation
- : public IndexedDBTransaction::Operation {
- public:
- CursorIterationOperation(scoped_refptr<IndexedDBCursor> cursor,
- scoped_ptr<IndexedDBKey> key,
- scoped_refptr<IndexedDBCallbacks> callbacks)
- : cursor_(cursor), key_(key.Pass()), callbacks_(callbacks) {}
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
-
- private:
- scoped_refptr<IndexedDBCursor> cursor_;
- scoped_ptr<IndexedDBKey> key_;
- scoped_refptr<IndexedDBCallbacks> callbacks_;
-};
-
-class IndexedDBCursor::CursorAdvanceOperation
- : public IndexedDBTransaction::Operation {
- public:
- CursorAdvanceOperation(scoped_refptr<IndexedDBCursor> cursor,
- uint32 count,
- scoped_refptr<IndexedDBCallbacks> callbacks)
- : cursor_(cursor), count_(count), callbacks_(callbacks) {}
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
-
- private:
- scoped_refptr<IndexedDBCursor> cursor_;
- uint32 count_;
- scoped_refptr<IndexedDBCallbacks> callbacks_;
-};
-
-class IndexedDBCursor::CursorPrefetchIterationOperation
- : public IndexedDBTransaction::Operation {
- public:
- CursorPrefetchIterationOperation(scoped_refptr<IndexedDBCursor> cursor,
- int number_to_fetch,
- scoped_refptr<IndexedDBCallbacks> callbacks)
- : cursor_(cursor),
- number_to_fetch_(number_to_fetch),
- callbacks_(callbacks) {}
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
-
- private:
- scoped_refptr<IndexedDBCursor> cursor_;
- int number_to_fetch_;
- scoped_refptr<IndexedDBCallbacks> callbacks_;
-};
-
IndexedDBCursor::IndexedDBCursor(
scoped_ptr<IndexedDBBackingStore::Cursor> cursor,
indexed_db::CursorType cursor_type,
@@ -81,7 +35,11 @@ void IndexedDBCursor::Continue(scoped_ptr<IndexedDBKey> key,
IDB_TRACE("IndexedDBCursor::Continue");
transaction_->ScheduleTask(
- task_type_, new CursorIterationOperation(this, key.Pass(), callbacks));
+ task_type_,
+ base::Bind(&IndexedDBCursor::CursorIterationOperation,
+ this,
+ base::Passed(&key),
+ callbacks));
}
void IndexedDBCursor::Advance(uint32 count,
@@ -89,35 +47,38 @@ void IndexedDBCursor::Advance(uint32 count,
IDB_TRACE("IndexedDBCursor::Advance");
transaction_->ScheduleTask(
- new CursorAdvanceOperation(this, count, callbacks));
+ task_type_,
+ base::Bind(
+ &IndexedDBCursor::CursorAdvanceOperation, this, count, callbacks));
}
-void IndexedDBCursor::CursorAdvanceOperation::Perform(
+void IndexedDBCursor::CursorAdvanceOperation(
+ uint32 count,
+ scoped_refptr<IndexedDBCallbacks> callbacks,
IndexedDBTransaction* /*transaction*/) {
- IDB_TRACE("CursorAdvanceOperation");
- if (!cursor_->cursor_ || !cursor_->cursor_->Advance(count_)) {
- cursor_->cursor_.reset();
- callbacks_->OnSuccess(static_cast<std::string*>(NULL));
+ IDB_TRACE("IndexedDBCursor::CursorAdvanceOperation");
+ if (!cursor_ || !cursor_->Advance(count)) {
+ cursor_.reset();
+ callbacks->OnSuccess(static_cast<std::string*>(NULL));
return;
}
- callbacks_->OnSuccess(
- cursor_->key(), cursor_->primary_key(), cursor_->Value());
+ callbacks->OnSuccess(key(), primary_key(), Value());
}
-void IndexedDBCursor::CursorIterationOperation::Perform(
+void IndexedDBCursor::CursorIterationOperation(
+ scoped_ptr<IndexedDBKey> key,
+ scoped_refptr<IndexedDBCallbacks> callbacks,
IndexedDBTransaction* /*transaction*/) {
- IDB_TRACE("CursorIterationOperation");
- if (!cursor_->cursor_ ||
- !cursor_->cursor_->Continue(key_.get(),
- IndexedDBBackingStore::Cursor::SEEK)) {
- cursor_->cursor_.reset();
- callbacks_->OnSuccess(static_cast<std::string*>(NULL));
+ IDB_TRACE("IndexedDBCursor::CursorIterationOperation");
+ if (!cursor_ ||
+ !cursor_->Continue(key.get(), IndexedDBBackingStore::Cursor::SEEK)) {
+ cursor_.reset();
+ callbacks->OnSuccess(static_cast<std::string*>(NULL));
return;
}
- callbacks_->OnSuccess(
- cursor_->key(), cursor_->primary_key(), cursor_->Value());
+ callbacks->OnSuccess(this->key(), primary_key(), Value());
}
void IndexedDBCursor::PrefetchContinue(
@@ -127,38 +88,43 @@ void IndexedDBCursor::PrefetchContinue(
transaction_->ScheduleTask(
task_type_,
- new CursorPrefetchIterationOperation(this, number_to_fetch, callbacks));
+ base::Bind(&IndexedDBCursor::CursorPrefetchIterationOperation,
+ this,
+ number_to_fetch,
+ callbacks));
}
-void IndexedDBCursor::CursorPrefetchIterationOperation::Perform(
+void IndexedDBCursor::CursorPrefetchIterationOperation(
+ int number_to_fetch,
+ scoped_refptr<IndexedDBCallbacks> callbacks,
IndexedDBTransaction* /*transaction*/) {
- IDB_TRACE("CursorPrefetchIterationOperation");
+ IDB_TRACE("IndexedDBCursor::CursorPrefetchIterationOperation");
std::vector<IndexedDBKey> found_keys;
std::vector<IndexedDBKey> found_primary_keys;
std::vector<std::string> found_values;
- if (cursor_->cursor_)
- cursor_->saved_cursor_.reset(cursor_->cursor_->Clone());
+ if (cursor_)
+ saved_cursor_.reset(cursor_->Clone());
const size_t max_size_estimate = 10 * 1024 * 1024;
size_t size_estimate = 0;
- for (int i = 0; i < number_to_fetch_; ++i) {
- if (!cursor_->cursor_ || !cursor_->cursor_->Continue()) {
- cursor_->cursor_.reset();
+ for (int i = 0; i < number_to_fetch; ++i) {
+ if (!cursor_ || !cursor_->Continue()) {
+ cursor_.reset();
break;
}
- found_keys.push_back(cursor_->cursor_->key());
- found_primary_keys.push_back(cursor_->cursor_->primary_key());
+ found_keys.push_back(cursor_->key());
+ found_primary_keys.push_back(cursor_->primary_key());
- switch (cursor_->cursor_type_) {
+ switch (cursor_type_) {
case indexed_db::CURSOR_KEY_ONLY:
found_values.push_back(std::string());
break;
case indexed_db::CURSOR_KEY_AND_VALUE: {
std::string value;
- value.swap(*cursor_->cursor_->Value());
+ value.swap(*cursor_->Value());
size_estimate += value.size();
found_values.push_back(value);
break;
@@ -166,19 +132,19 @@ void IndexedDBCursor::CursorPrefetchIterationOperation::Perform(
default:
NOTREACHED();
}
- size_estimate += cursor_->cursor_->key().size_estimate();
- size_estimate += cursor_->cursor_->primary_key().size_estimate();
+ size_estimate += cursor_->key().size_estimate();
+ size_estimate += cursor_->primary_key().size_estimate();
if (size_estimate > max_size_estimate)
break;
}
if (!found_keys.size()) {
- callbacks_->OnSuccess(static_cast<std::string*>(NULL));
+ callbacks->OnSuccess(static_cast<std::string*>(NULL));
return;
}
- callbacks_->OnSuccessWithPrefetch(
+ callbacks->OnSuccessWithPrefetch(
found_keys, found_primary_keys, found_values);
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_cursor.h b/chromium/content/browser/indexed_db/indexed_db_cursor.h
index 2cf9d4f3ecc..db5963058e7 100644
--- a/chromium/content/browser/indexed_db/indexed_db_cursor.h
+++ b/chromium/content/browser/indexed_db/indexed_db_cursor.h
@@ -41,15 +41,22 @@ class CONTENT_EXPORT IndexedDBCursor
}
void Close();
+ void CursorIterationOperation(scoped_ptr<IndexedDBKey> key,
+ scoped_refptr<IndexedDBCallbacks> callbacks,
+ IndexedDBTransaction* transaction);
+ void CursorAdvanceOperation(uint32 count,
+ scoped_refptr<IndexedDBCallbacks> callbacks,
+ IndexedDBTransaction* transaction);
+ void CursorPrefetchIterationOperation(
+ int number_to_fetch,
+ scoped_refptr<IndexedDBCallbacks> callbacks,
+ IndexedDBTransaction* transaction);
+
private:
friend class base::RefCounted<IndexedDBCursor>;
~IndexedDBCursor();
- class CursorIterationOperation;
- class CursorAdvanceOperation;
- class CursorPrefetchIterationOperation;
-
IndexedDBDatabase::TaskType task_type_;
indexed_db::CursorType cursor_type_;
const scoped_refptr<IndexedDBTransaction> transaction_;
diff --git a/chromium/content/browser/indexed_db/indexed_db_database.cc b/chromium/content/browser/indexed_db/indexed_db_database.cc
index 9eb577448df..f7b2a9bcff8 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_database.cc
@@ -29,345 +29,6 @@ using WebKit::WebIDBKeyTypeNumber;
namespace content {
-class CreateObjectStoreOperation : public IndexedDBTransaction::Operation {
- public:
- CreateObjectStoreOperation(
- scoped_refptr<IndexedDBBackingStore> backing_store,
- const IndexedDBObjectStoreMetadata& object_store_metadata)
- : backing_store_(backing_store),
- object_store_metadata_(object_store_metadata) {}
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
-
- private:
- const scoped_refptr<IndexedDBBackingStore> backing_store_;
- const IndexedDBObjectStoreMetadata object_store_metadata_;
-};
-
-class DeleteObjectStoreOperation : public IndexedDBTransaction::Operation {
- public:
- DeleteObjectStoreOperation(
- scoped_refptr<IndexedDBBackingStore> backing_store,
- const IndexedDBObjectStoreMetadata& object_store_metadata)
- : backing_store_(backing_store),
- object_store_metadata_(object_store_metadata) {}
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
-
- private:
- const scoped_refptr<IndexedDBBackingStore> backing_store_;
- const IndexedDBObjectStoreMetadata object_store_metadata_;
-};
-
-class IndexedDBDatabase::VersionChangeOperation
- : public IndexedDBTransaction::Operation {
- public:
- VersionChangeOperation(scoped_refptr<IndexedDBDatabase> database,
- int64 transaction_id,
- int64 version,
- scoped_refptr<IndexedDBCallbacks> callbacks,
- scoped_ptr<IndexedDBConnection> connection,
- WebKit::WebIDBCallbacks::DataLoss data_loss)
- : database_(database),
- transaction_id_(transaction_id),
- version_(version),
- callbacks_(callbacks),
- connection_(connection.Pass()),
- data_loss_(data_loss) {}
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
-
- private:
- scoped_refptr<IndexedDBDatabase> database_;
- int64 transaction_id_;
- int64 version_;
- scoped_refptr<IndexedDBCallbacks> callbacks_;
- scoped_ptr<IndexedDBConnection> connection_;
- WebKit::WebIDBCallbacks::DataLoss data_loss_;
-};
-
-class CreateObjectStoreAbortOperation : public IndexedDBTransaction::Operation {
- public:
- CreateObjectStoreAbortOperation(scoped_refptr<IndexedDBDatabase> database,
- int64 object_store_id)
- : database_(database), object_store_id_(object_store_id) {}
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
-
- private:
- const scoped_refptr<IndexedDBDatabase> database_;
- const int64 object_store_id_;
-};
-
-class DeleteObjectStoreAbortOperation : public IndexedDBTransaction::Operation {
- public:
- DeleteObjectStoreAbortOperation(
- scoped_refptr<IndexedDBDatabase> database,
- const IndexedDBObjectStoreMetadata& object_store_metadata)
- : database_(database), object_store_metadata_(object_store_metadata) {}
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
-
- private:
- scoped_refptr<IndexedDBDatabase> database_;
- IndexedDBObjectStoreMetadata object_store_metadata_;
-};
-
-class IndexedDBDatabase::VersionChangeAbortOperation
- : public IndexedDBTransaction::Operation {
- public:
- VersionChangeAbortOperation(scoped_refptr<IndexedDBDatabase> database,
- const string16& previous_version,
- int64 previous_int_version)
- : database_(database),
- previous_version_(previous_version),
- previous_int_version_(previous_int_version) {}
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
-
- private:
- scoped_refptr<IndexedDBDatabase> database_;
- string16 previous_version_;
- int64 previous_int_version_;
-};
-
-class CreateIndexOperation : public IndexedDBTransaction::Operation {
- public:
- CreateIndexOperation(scoped_refptr<IndexedDBBackingStore> backing_store,
- int64 object_store_id,
- const IndexedDBIndexMetadata& index_metadata)
- : backing_store_(backing_store),
- object_store_id_(object_store_id),
- index_metadata_(index_metadata) {}
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
-
- private:
- const scoped_refptr<IndexedDBBackingStore> backing_store_;
- const int64 object_store_id_;
- const IndexedDBIndexMetadata index_metadata_;
-};
-
-class DeleteIndexOperation : public IndexedDBTransaction::Operation {
- public:
- DeleteIndexOperation(scoped_refptr<IndexedDBBackingStore> backing_store,
- int64 object_store_id,
- const IndexedDBIndexMetadata& index_metadata)
- : backing_store_(backing_store),
- object_store_id_(object_store_id),
- index_metadata_(index_metadata) {}
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
-
- private:
- const scoped_refptr<IndexedDBBackingStore> backing_store_;
- const int64 object_store_id_;
- const IndexedDBIndexMetadata index_metadata_;
-};
-
-class CreateIndexAbortOperation : public IndexedDBTransaction::Operation {
- public:
- CreateIndexAbortOperation(scoped_refptr<IndexedDBDatabase> database,
- int64 object_store_id,
- int64 index_id)
- : database_(database),
- object_store_id_(object_store_id),
- index_id_(index_id) {}
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
-
- private:
- const scoped_refptr<IndexedDBDatabase> database_;
- const int64 object_store_id_;
- const int64 index_id_;
-};
-
-class DeleteIndexAbortOperation : public IndexedDBTransaction::Operation {
- public:
- DeleteIndexAbortOperation(scoped_refptr<IndexedDBDatabase> database,
- int64 object_store_id,
- const IndexedDBIndexMetadata& index_metadata)
- : database_(database),
- object_store_id_(object_store_id),
- index_metadata_(index_metadata) {}
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
-
- private:
- const scoped_refptr<IndexedDBDatabase> database_;
- const int64 object_store_id_;
- const IndexedDBIndexMetadata index_metadata_;
-};
-
-class GetOperation : public IndexedDBTransaction::Operation {
- public:
- GetOperation(scoped_refptr<IndexedDBBackingStore> backing_store,
- int64 database_id,
- int64 object_store_id,
- int64 index_id,
- const IndexedDBKeyPath& key_path,
- const bool auto_increment,
- scoped_ptr<IndexedDBKeyRange> key_range,
- indexed_db::CursorType cursor_type,
- scoped_refptr<IndexedDBCallbacks> callbacks)
- : backing_store_(backing_store),
- database_id_(database_id),
- object_store_id_(object_store_id),
- index_id_(index_id),
- key_path_(key_path),
- auto_increment_(auto_increment),
- key_range_(key_range.Pass()),
- cursor_type_(cursor_type),
- callbacks_(callbacks) {}
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
-
- private:
- const scoped_refptr<IndexedDBBackingStore> backing_store_;
- const int64 database_id_;
- const int64 object_store_id_;
- const int64 index_id_;
- const IndexedDBKeyPath key_path_;
- const bool auto_increment_;
- const scoped_ptr<IndexedDBKeyRange> key_range_;
- const indexed_db::CursorType cursor_type_;
- const scoped_refptr<IndexedDBCallbacks> callbacks_;
-};
-
-class PutOperation : public IndexedDBTransaction::Operation {
- public:
- PutOperation(scoped_refptr<IndexedDBBackingStore> backing_store,
- int64 database_id,
- const IndexedDBObjectStoreMetadata& object_store,
- std::string* value,
- scoped_ptr<IndexedDBKey> key,
- IndexedDBDatabase::PutMode put_mode,
- scoped_refptr<IndexedDBCallbacks> callbacks,
- const std::vector<int64>& index_ids,
- const std::vector<IndexedDBDatabase::IndexKeys>& index_keys)
- : backing_store_(backing_store),
- database_id_(database_id),
- object_store_(object_store),
- key_(key.Pass()),
- put_mode_(put_mode),
- callbacks_(callbacks),
- index_ids_(index_ids),
- index_keys_(index_keys) {
- value_.swap(*value);
- }
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
-
- private:
- const scoped_refptr<IndexedDBBackingStore> backing_store_;
- const int64 database_id_;
- const IndexedDBObjectStoreMetadata object_store_;
- std::string value_;
- scoped_ptr<IndexedDBKey> key_;
- const IndexedDBDatabase::PutMode put_mode_;
- const scoped_refptr<IndexedDBCallbacks> callbacks_;
- const std::vector<int64> index_ids_;
- const std::vector<IndexedDBDatabase::IndexKeys> index_keys_;
-};
-
-class SetIndexesReadyOperation : public IndexedDBTransaction::Operation {
- public:
- explicit SetIndexesReadyOperation(size_t index_count)
- : index_count_(index_count) {}
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
-
- private:
- const size_t index_count_;
-};
-
-class OpenCursorOperation : public IndexedDBTransaction::Operation {
- public:
- OpenCursorOperation(scoped_refptr<IndexedDBBackingStore> backing_store,
- int64 database_id,
- int64 object_store_id,
- int64 index_id,
- scoped_ptr<IndexedDBKeyRange> key_range,
- indexed_db::CursorDirection direction,
- indexed_db::CursorType cursor_type,
- IndexedDBDatabase::TaskType task_type,
- scoped_refptr<IndexedDBCallbacks> callbacks)
- : backing_store_(backing_store),
- database_id_(database_id),
- object_store_id_(object_store_id),
- index_id_(index_id),
- key_range_(key_range.Pass()),
- direction_(direction),
- cursor_type_(cursor_type),
- task_type_(task_type),
- callbacks_(callbacks) {}
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
-
- private:
- const scoped_refptr<IndexedDBBackingStore> backing_store_;
- const int64 database_id_;
- const int64 object_store_id_;
- const int64 index_id_;
- const scoped_ptr<IndexedDBKeyRange> key_range_;
- const indexed_db::CursorDirection direction_;
- const indexed_db::CursorType cursor_type_;
- const IndexedDBDatabase::TaskType task_type_;
- const scoped_refptr<IndexedDBCallbacks> callbacks_;
-};
-
-class CountOperation : public IndexedDBTransaction::Operation {
- public:
- CountOperation(scoped_refptr<IndexedDBBackingStore> backing_store,
- int64 database_id,
- int64 object_store_id,
- int64 index_id,
- scoped_ptr<IndexedDBKeyRange> key_range,
- scoped_refptr<IndexedDBCallbacks> callbacks)
- : backing_store_(backing_store),
- database_id_(database_id),
- object_store_id_(object_store_id),
- index_id_(index_id),
- key_range_(key_range.Pass()),
- callbacks_(callbacks) {}
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
-
- private:
- const scoped_refptr<IndexedDBBackingStore> backing_store_;
- const int64 database_id_;
- const int64 object_store_id_;
- const int64 index_id_;
- const scoped_ptr<IndexedDBKeyRange> key_range_;
- const scoped_refptr<IndexedDBCallbacks> callbacks_;
-};
-
-class DeleteRangeOperation : public IndexedDBTransaction::Operation {
- public:
- DeleteRangeOperation(scoped_refptr<IndexedDBBackingStore> backing_store,
- int64 database_id,
- int64 object_store_id,
- scoped_ptr<IndexedDBKeyRange> key_range,
- scoped_refptr<IndexedDBCallbacks> callbacks)
- : backing_store_(backing_store),
- database_id_(database_id),
- object_store_id_(object_store_id),
- key_range_(key_range.Pass()),
- callbacks_(callbacks) {}
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
-
- private:
- const scoped_refptr<IndexedDBBackingStore> backing_store_;
- const int64 database_id_;
- const int64 object_store_id_;
- const scoped_ptr<IndexedDBKeyRange> key_range_;
- const scoped_refptr<IndexedDBCallbacks> callbacks_;
-};
-
-class ClearOperation : public IndexedDBTransaction::Operation {
- public:
- ClearOperation(scoped_refptr<IndexedDBBackingStore> backing_store,
- int64 database_id,
- int64 object_store_id,
- scoped_refptr<IndexedDBCallbacks> callbacks)
- : backing_store_(backing_store),
- database_id_(database_id),
- object_store_id_(object_store_id),
- callbacks_(callbacks) {}
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
-
- private:
- const scoped_refptr<IndexedDBBackingStore> backing_store_;
- const int64 database_id_;
- const int64 object_store_id_;
- const scoped_refptr<IndexedDBCallbacks> callbacks_;
-};
-
// PendingOpenCall has a scoped_refptr<IndexedDBDatabaseCallbacks> because it
// isn't a connection yet.
class IndexedDBDatabase::PendingOpenCall {
@@ -455,14 +116,14 @@ class IndexedDBDatabase::PendingDeleteCall {
scoped_refptr<IndexedDBDatabase> IndexedDBDatabase::Create(
const string16& name,
- IndexedDBBackingStore* database,
+ IndexedDBBackingStore* backing_store,
IndexedDBFactory* factory,
const Identifier& unique_identifier) {
- scoped_refptr<IndexedDBDatabase> backend =
- new IndexedDBDatabase(name, database, factory, unique_identifier);
- if (!backend->OpenInternal())
+ scoped_refptr<IndexedDBDatabase> database =
+ new IndexedDBDatabase(name, backing_store, factory, unique_identifier);
+ if (!database->OpenInternal())
return 0;
- return backend;
+ return database;
}
namespace {
@@ -474,11 +135,10 @@ bool Contains(const T& container, const U& item) {
}
}
-IndexedDBDatabase::IndexedDBDatabase(
- const string16& name,
- IndexedDBBackingStore* backing_store,
- IndexedDBFactory* factory,
- const Identifier& unique_identifier)
+IndexedDBDatabase::IndexedDBDatabase(const string16& name,
+ IndexedDBBackingStore* backing_store,
+ IndexedDBFactory* factory,
+ const Identifier& unique_identifier)
: backing_store_(backing_store),
metadata_(name,
kInvalidId,
@@ -647,25 +307,31 @@ void IndexedDBDatabase::CreateObjectStore(int64 transaction_id,
IndexedDBDatabase::kMinimumIndexId);
transaction->ScheduleTask(
- new CreateObjectStoreOperation(backing_store_, object_store_metadata),
- new CreateObjectStoreAbortOperation(this, object_store_id));
+ base::Bind(&IndexedDBDatabase::CreateObjectStoreOperation,
+ this,
+ object_store_metadata),
+ base::Bind(&IndexedDBDatabase::CreateObjectStoreAbortOperation,
+ this,
+ object_store_id));
AddObjectStore(object_store_metadata, object_store_id);
}
-void CreateObjectStoreOperation::Perform(IndexedDBTransaction* transaction) {
- IDB_TRACE("CreateObjectStoreOperation");
+void IndexedDBDatabase::CreateObjectStoreOperation(
+ const IndexedDBObjectStoreMetadata& object_store_metadata,
+ IndexedDBTransaction* transaction) {
+ IDB_TRACE("IndexedDBDatabase::CreateObjectStoreOperation");
if (!backing_store_->CreateObjectStore(
transaction->BackingStoreTransaction(),
transaction->database()->id(),
- object_store_metadata_.id,
- object_store_metadata_.name,
- object_store_metadata_.key_path,
- object_store_metadata_.auto_increment)) {
+ object_store_metadata.id,
+ object_store_metadata.name,
+ object_store_metadata.key_path,
+ object_store_metadata.auto_increment)) {
transaction->Abort(IndexedDBDatabaseError(
WebKit::WebIDBDatabaseExceptionUnknownError,
ASCIIToUTF16("Internal error creating object store '") +
- object_store_metadata_.name + ASCIIToUTF16("'.")));
+ object_store_metadata.name + ASCIIToUTF16("'.")));
return;
}
}
@@ -685,8 +351,12 @@ void IndexedDBDatabase::DeleteObjectStore(int64 transaction_id,
metadata_.object_stores[object_store_id];
transaction->ScheduleTask(
- new DeleteObjectStoreOperation(backing_store_, object_store_metadata),
- new DeleteObjectStoreAbortOperation(this, object_store_metadata));
+ base::Bind(&IndexedDBDatabase::DeleteObjectStoreOperation,
+ this,
+ object_store_metadata),
+ base::Bind(&IndexedDBDatabase::DeleteObjectStoreAbortOperation,
+ this,
+ object_store_metadata));
RemoveObjectStore(object_store_id);
}
@@ -709,34 +379,46 @@ void IndexedDBDatabase::CreateIndex(int64 transaction_id,
name, index_id, key_path, unique, multi_entry);
transaction->ScheduleTask(
- new CreateIndexOperation(backing_store_, object_store_id, index_metadata),
- new CreateIndexAbortOperation(this, object_store_id, index_id));
+ base::Bind(&IndexedDBDatabase::CreateIndexOperation,
+ this,
+ object_store_id,
+ index_metadata),
+ base::Bind(&IndexedDBDatabase::CreateIndexAbortOperation,
+ this,
+ object_store_id,
+ index_id));
AddIndex(object_store_id, index_metadata, index_id);
}
-void CreateIndexOperation::Perform(IndexedDBTransaction* transaction) {
- IDB_TRACE("CreateIndexOperation");
+void IndexedDBDatabase::CreateIndexOperation(
+ int64 object_store_id,
+ const IndexedDBIndexMetadata& index_metadata,
+ IndexedDBTransaction* transaction) {
+ IDB_TRACE("IndexedDBDatabase::CreateIndexOperation");
if (!backing_store_->CreateIndex(transaction->BackingStoreTransaction(),
transaction->database()->id(),
- object_store_id_,
- index_metadata_.id,
- index_metadata_.name,
- index_metadata_.key_path,
- index_metadata_.unique,
- index_metadata_.multi_entry)) {
+ object_store_id,
+ index_metadata.id,
+ index_metadata.name,
+ index_metadata.key_path,
+ index_metadata.unique,
+ index_metadata.multi_entry)) {
string16 error_string = ASCIIToUTF16("Internal error creating index '") +
- index_metadata_.name + ASCIIToUTF16("'.");
+ index_metadata.name + ASCIIToUTF16("'.");
transaction->Abort(IndexedDBDatabaseError(
WebKit::WebIDBDatabaseExceptionUnknownError, error_string));
return;
}
}
-void CreateIndexAbortOperation::Perform(IndexedDBTransaction* transaction) {
- IDB_TRACE("CreateIndexAbortOperation");
+void IndexedDBDatabase::CreateIndexAbortOperation(
+ int64 object_store_id,
+ int64 index_id,
+ IndexedDBTransaction* transaction) {
+ IDB_TRACE("IndexedDBDatabase::CreateIndexAbortOperation");
DCHECK(!transaction);
- database_->RemoveIndex(object_store_id_, index_id_);
+ RemoveIndex(object_store_id, index_id);
}
void IndexedDBDatabase::DeleteIndex(int64 transaction_id,
@@ -754,31 +436,42 @@ void IndexedDBDatabase::DeleteIndex(int64 transaction_id,
metadata_.object_stores[object_store_id].indexes[index_id];
transaction->ScheduleTask(
- new DeleteIndexOperation(backing_store_, object_store_id, index_metadata),
- new DeleteIndexAbortOperation(this, object_store_id, index_metadata));
+ base::Bind(&IndexedDBDatabase::DeleteIndexOperation,
+ this,
+ object_store_id,
+ index_metadata),
+ base::Bind(&IndexedDBDatabase::DeleteIndexAbortOperation,
+ this,
+ object_store_id,
+ index_metadata));
RemoveIndex(object_store_id, index_id);
}
-void DeleteIndexOperation::Perform(IndexedDBTransaction* transaction) {
- IDB_TRACE("DeleteIndexOperation");
+void IndexedDBDatabase::DeleteIndexOperation(
+ int64 object_store_id,
+ const IndexedDBIndexMetadata& index_metadata,
+ IndexedDBTransaction* transaction) {
+ IDB_TRACE("IndexedDBDatabase::DeleteIndexOperation");
bool ok = backing_store_->DeleteIndex(transaction->BackingStoreTransaction(),
transaction->database()->id(),
- object_store_id_,
- index_metadata_.id);
+ object_store_id,
+ index_metadata.id);
if (!ok) {
string16 error_string = ASCIIToUTF16("Internal error deleting index '") +
- index_metadata_.name + ASCIIToUTF16("'.");
+ index_metadata.name + ASCIIToUTF16("'.");
transaction->Abort(IndexedDBDatabaseError(
WebKit::WebIDBDatabaseExceptionUnknownError, error_string));
}
}
-void DeleteIndexAbortOperation::Perform(IndexedDBTransaction* transaction) {
- IDB_TRACE("DeleteIndexAbortOperation");
+void IndexedDBDatabase::DeleteIndexAbortOperation(
+ int64 object_store_id,
+ const IndexedDBIndexMetadata& index_metadata,
+ IndexedDBTransaction* transaction) {
+ IDB_TRACE("IndexedDBDatabase::DeleteIndexAbortOperation");
DCHECK(!transaction);
- database_->AddIndex(
- object_store_id_, index_metadata_, IndexedDBIndexMetadata::kInvalidId);
+ AddIndex(object_store_id, index_metadata, IndexedDBIndexMetadata::kInvalidId);
}
void IndexedDBDatabase::Commit(int64 transaction_id) {
@@ -821,61 +514,68 @@ void IndexedDBDatabase::Get(int64 transaction_id,
if (!ValidateObjectStoreIdAndOptionalIndexId(object_store_id, index_id))
return;
- const IndexedDBObjectStoreMetadata& object_store_metadata =
- metadata_.object_stores[object_store_id];
- transaction->ScheduleTask(new GetOperation(
- backing_store_,
- metadata_.id,
+ transaction->ScheduleTask(base::Bind(
+ &IndexedDBDatabase::GetOperation,
+ this,
object_store_id,
index_id,
- object_store_metadata.key_path,
- object_store_metadata.auto_increment,
- key_range.Pass(),
+ Passed(&key_range),
key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE,
callbacks));
}
-void GetOperation::Perform(IndexedDBTransaction* transaction) {
- IDB_TRACE("GetOperation");
+void IndexedDBDatabase::GetOperation(
+ int64 object_store_id,
+ int64 index_id,
+ scoped_ptr<IndexedDBKeyRange> key_range,
+ indexed_db::CursorType cursor_type,
+ scoped_refptr<IndexedDBCallbacks> callbacks,
+ IndexedDBTransaction* transaction) {
+ IDB_TRACE("IndexedDBDatabase::GetOperation");
+
+ DCHECK(metadata_.object_stores.find(object_store_id) !=
+ metadata_.object_stores.end());
+ const IndexedDBObjectStoreMetadata& object_store_metadata =
+ metadata_.object_stores[object_store_id];
const IndexedDBKey* key;
scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
- if (key_range_->IsOnlyKey()) {
- key = &key_range_->lower();
+ if (key_range->IsOnlyKey()) {
+ key = &key_range->lower();
} else {
- if (index_id_ == IndexedDBIndexMetadata::kInvalidId) {
- DCHECK_NE(cursor_type_, indexed_db::CURSOR_KEY_ONLY);
+ if (index_id == IndexedDBIndexMetadata::kInvalidId) {
+ DCHECK_NE(cursor_type, indexed_db::CURSOR_KEY_ONLY);
// ObjectStore Retrieval Operation
backing_store_cursor = backing_store_->OpenObjectStoreCursor(
transaction->BackingStoreTransaction(),
- database_id_,
- object_store_id_,
- *key_range_,
+ id(),
+ object_store_id,
+ *key_range,
indexed_db::CURSOR_NEXT);
- } else if (cursor_type_ == indexed_db::CURSOR_KEY_ONLY) {
+ } else if (cursor_type == indexed_db::CURSOR_KEY_ONLY) {
// Index Value Retrieval Operation
backing_store_cursor = backing_store_->OpenIndexKeyCursor(
transaction->BackingStoreTransaction(),
- database_id_,
- object_store_id_,
- index_id_,
- *key_range_,
+ id(),
+ object_store_id,
+ index_id,
+ *key_range,
indexed_db::CURSOR_NEXT);
} else {
// Index Referenced Value Retrieval Operation
backing_store_cursor = backing_store_->OpenIndexCursor(
transaction->BackingStoreTransaction(),
- database_id_,
- object_store_id_,
- index_id_,
- *key_range_,
+ id(),
+ object_store_id,
+ index_id,
+ *key_range,
indexed_db::CURSOR_NEXT);
}
if (!backing_store_cursor) {
- callbacks_->OnSuccess();
+ callbacks->OnSuccess();
return;
}
@@ -884,82 +584,84 @@ void GetOperation::Perform(IndexedDBTransaction* transaction) {
scoped_ptr<IndexedDBKey> primary_key;
bool ok;
- if (index_id_ == IndexedDBIndexMetadata::kInvalidId) {
+ if (index_id == IndexedDBIndexMetadata::kInvalidId) {
// Object Store Retrieval Operation
std::string value;
ok = backing_store_->GetRecord(transaction->BackingStoreTransaction(),
- database_id_,
- object_store_id_,
+ id(),
+ object_store_id,
*key,
&value);
if (!ok) {
- callbacks_->OnError(
+ callbacks->OnError(
IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
"Internal error in GetRecord."));
return;
}
if (value.empty()) {
- callbacks_->OnSuccess();
+ callbacks->OnSuccess();
return;
}
- if (auto_increment_ && !key_path_.IsNull()) {
- callbacks_->OnSuccess(&value, *key, key_path_);
+ if (object_store_metadata.auto_increment &&
+ !object_store_metadata.key_path.IsNull()) {
+ callbacks->OnSuccess(&value, *key, object_store_metadata.key_path);
return;
}
- callbacks_->OnSuccess(&value);
+ callbacks->OnSuccess(&value);
return;
}
// From here we are dealing only with indexes.
ok = backing_store_->GetPrimaryKeyViaIndex(
transaction->BackingStoreTransaction(),
- database_id_,
- object_store_id_,
- index_id_,
+ id(),
+ object_store_id,
+ index_id,
*key,
&primary_key);
if (!ok) {
- callbacks_->OnError(
+ callbacks->OnError(
IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
"Internal error in GetPrimaryKeyViaIndex."));
return;
}
if (!primary_key) {
- callbacks_->OnSuccess();
+ callbacks->OnSuccess();
return;
}
- if (cursor_type_ == indexed_db::CURSOR_KEY_ONLY) {
+ if (cursor_type == indexed_db::CURSOR_KEY_ONLY) {
// Index Value Retrieval Operation
- callbacks_->OnSuccess(*primary_key);
+ callbacks->OnSuccess(*primary_key);
return;
}
// Index Referenced Value Retrieval Operation
std::string value;
ok = backing_store_->GetRecord(transaction->BackingStoreTransaction(),
- database_id_,
- object_store_id_,
+ id(),
+ object_store_id,
*primary_key,
&value);
if (!ok) {
- callbacks_->OnError(
+ callbacks->OnError(
IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
"Internal error in GetRecord."));
return;
}
if (value.empty()) {
- callbacks_->OnSuccess();
+ callbacks->OnSuccess();
return;
}
- if (auto_increment_ && !key_path_.IsNull()) {
- callbacks_->OnSuccess(&value, *primary_key, key_path_);
+ if (object_store_metadata.auto_increment &&
+ !object_store_metadata.key_path.IsNull()) {
+ callbacks->OnSuccess(&value, *primary_key, object_store_metadata.key_path);
return;
}
- callbacks_->OnSuccess(&value);
+ callbacks->OnSuccess(&value);
}
static scoped_ptr<IndexedDBKey> GenerateKey(
@@ -982,8 +684,7 @@ static scoped_ptr<IndexedDBKey> GenerateKey(
if (current_number < 0 || current_number > max_generator_value)
return make_scoped_ptr(new IndexedDBKey());
- return make_scoped_ptr(
- new IndexedDBKey(current_number, WebIDBKeyTypeNumber));
+ return make_scoped_ptr(new IndexedDBKey(current_number, WebIDBKeyTypeNumber));
}
static bool UpdateKeyGenerator(
@@ -991,18 +692,30 @@ static bool UpdateKeyGenerator(
scoped_refptr<IndexedDBTransaction> transaction,
int64 database_id,
int64 object_store_id,
- const IndexedDBKey* key,
+ const IndexedDBKey& key,
bool check_current) {
- DCHECK(key);
- DCHECK_EQ(WebIDBKeyTypeNumber, key->type());
+ DCHECK_EQ(WebIDBKeyTypeNumber, key.type());
return backing_store->MaybeUpdateKeyGeneratorCurrentNumber(
transaction->BackingStoreTransaction(),
database_id,
object_store_id,
- static_cast<int64>(floor(key->number())) + 1,
+ static_cast<int64>(floor(key.number())) + 1,
check_current);
}
+struct IndexedDBDatabase::PutOperationParams {
+ PutOperationParams() {}
+ int64 object_store_id;
+ std::string value;
+ scoped_ptr<IndexedDBKey> key;
+ IndexedDBDatabase::PutMode put_mode;
+ scoped_refptr<IndexedDBCallbacks> callbacks;
+ std::vector<int64> index_ids;
+ std::vector<IndexKeys> index_keys;
+
+ DISALLOW_COPY_AND_ASSIGN(PutOperationParams);
+};
+
void IndexedDBDatabase::Put(int64 transaction_id,
int64 object_store_id,
std::string* value,
@@ -1019,65 +732,70 @@ void IndexedDBDatabase::Put(int64 transaction_id,
if (!ValidateObjectStoreId(object_store_id))
return;
- const IndexedDBObjectStoreMetadata& object_store_metadata =
- metadata_.object_stores[object_store_id];
DCHECK(key);
- DCHECK(object_store_metadata.auto_increment || key->IsValid());
- transaction->ScheduleTask(new PutOperation(backing_store_,
- id(),
- object_store_metadata,
- value,
- key.Pass(),
- put_mode,
- callbacks,
- index_ids,
- index_keys));
-}
-
-void PutOperation::Perform(IndexedDBTransaction* transaction) {
- IDB_TRACE("PutOperation");
+ scoped_ptr<PutOperationParams> params(new PutOperationParams());
+ params->object_store_id = object_store_id;
+ params->value.swap(*value);
+ params->key = key.Pass();
+ params->put_mode = put_mode;
+ params->callbacks = callbacks;
+ params->index_ids = index_ids;
+ params->index_keys = index_keys;
+ transaction->ScheduleTask(base::Bind(
+ &IndexedDBDatabase::PutOperation, this, base::Passed(&params)));
+}
+
+void IndexedDBDatabase::PutOperation(scoped_ptr<PutOperationParams> params,
+ IndexedDBTransaction* transaction) {
+ IDB_TRACE("IndexedDBDatabase::PutOperation");
DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY);
- DCHECK_EQ(index_ids_.size(), index_keys_.size());
+ DCHECK_EQ(params->index_ids.size(), params->index_keys.size());
bool key_was_generated = false;
+ DCHECK(metadata_.object_stores.find(params->object_store_id) !=
+ metadata_.object_stores.end());
+ const IndexedDBObjectStoreMetadata& object_store =
+ metadata_.object_stores[params->object_store_id];
+ DCHECK(object_store.auto_increment || params->key->IsValid());
+
scoped_ptr<IndexedDBKey> key;
- if (put_mode_ != IndexedDBDatabase::CURSOR_UPDATE &&
- object_store_.auto_increment && !key_->IsValid()) {
- scoped_ptr<IndexedDBKey> auto_inc_key = GenerateKey(
- backing_store_, transaction, database_id_, object_store_.id);
+ if (params->put_mode != IndexedDBDatabase::CURSOR_UPDATE &&
+ object_store.auto_increment && !params->key->IsValid()) {
+ scoped_ptr<IndexedDBKey> auto_inc_key =
+ GenerateKey(backing_store_, transaction, id(), params->object_store_id);
key_was_generated = true;
if (!auto_inc_key->IsValid()) {
- callbacks_->OnError(
+ params->callbacks->OnError(
IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionConstraintError,
"Maximum key generator value reached."));
return;
}
key = auto_inc_key.Pass();
} else {
- key = key_.Pass();
+ key = params->key.Pass();
}
DCHECK(key->IsValid());
IndexedDBBackingStore::RecordIdentifier record_identifier;
- if (put_mode_ == IndexedDBDatabase::ADD_ONLY) {
+ if (params->put_mode == IndexedDBDatabase::ADD_ONLY) {
bool found = false;
bool ok = backing_store_->KeyExistsInObjectStore(
transaction->BackingStoreTransaction(),
- database_id_,
- object_store_.id,
- *key.get(),
+ id(),
+ params->object_store_id,
+ *key,
&record_identifier,
&found);
if (!ok) {
- callbacks_->OnError(
+ params->callbacks->OnError(
IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
"Internal error checking key existence."));
return;
}
if (found) {
- callbacks_->OnError(
+ params->callbacks->OnError(
IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionConstraintError,
"Key already exists in the object store."));
return;
@@ -1088,24 +806,24 @@ void PutOperation::Perform(IndexedDBTransaction* transaction) {
string16 error_message;
bool obeys_constraints = false;
bool backing_store_success = MakeIndexWriters(transaction,
- backing_store_,
- database_id_,
- object_store_,
+ backing_store_.get(),
+ id(),
+ object_store,
*key,
key_was_generated,
- index_ids_,
- index_keys_,
+ params->index_ids,
+ params->index_keys,
&index_writers,
&error_message,
&obeys_constraints);
if (!backing_store_success) {
- callbacks_->OnError(IndexedDBDatabaseError(
+ params->callbacks->OnError(IndexedDBDatabaseError(
WebKit::WebIDBDatabaseExceptionUnknownError,
"Internal error: backing store error updating index keys."));
return;
}
if (!obeys_constraints) {
- callbacks_->OnError(IndexedDBDatabaseError(
+ params->callbacks->OnError(IndexedDBDatabaseError(
WebKit::WebIDBDatabaseExceptionConstraintError, error_message));
return;
}
@@ -1114,13 +832,13 @@ void PutOperation::Perform(IndexedDBTransaction* transaction) {
// transaction in case of error.
backing_store_success =
backing_store_->PutRecord(transaction->BackingStoreTransaction(),
- database_id_,
- object_store_.id,
- *key.get(),
- value_,
+ id(),
+ params->object_store_id,
+ *key,
+ params->value,
&record_identifier);
if (!backing_store_success) {
- callbacks_->OnError(IndexedDBDatabaseError(
+ params->callbacks->OnError(IndexedDBDatabaseError(
WebKit::WebIDBDatabaseExceptionUnknownError,
"Internal error: backing store error performing put/add."));
return;
@@ -1129,30 +847,30 @@ void PutOperation::Perform(IndexedDBTransaction* transaction) {
for (size_t i = 0; i < index_writers.size(); ++i) {
IndexWriter* index_writer = index_writers[i];
index_writer->WriteIndexKeys(record_identifier,
- backing_store_,
+ backing_store_.get(),
transaction->BackingStoreTransaction(),
- database_id_,
- object_store_.id);
+ id(),
+ params->object_store_id);
}
- if (object_store_.auto_increment &&
- put_mode_ != IndexedDBDatabase::CURSOR_UPDATE &&
+ if (object_store.auto_increment &&
+ params->put_mode != IndexedDBDatabase::CURSOR_UPDATE &&
key->type() == WebIDBKeyTypeNumber) {
bool ok = UpdateKeyGenerator(backing_store_,
transaction,
- database_id_,
- object_store_.id,
- key.get(),
+ id(),
+ params->object_store_id,
+ *key,
!key_was_generated);
if (!ok) {
- callbacks_->OnError(
+ params->callbacks->OnError(
IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
"Internal error updating key generator."));
return;
}
}
- callbacks_->OnSuccess(*key);
+ params->callbacks->OnSuccess(*key);
}
void IndexedDBDatabase::SetIndexKeys(int64 transaction_id,
@@ -1240,16 +958,34 @@ void IndexedDBDatabase::SetIndexesReady(int64 transaction_id,
return;
DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
- transaction->ScheduleTask(IndexedDBDatabase::PREEMPTIVE_TASK,
- new SetIndexesReadyOperation(index_ids.size()));
+ transaction->ScheduleTask(
+ IndexedDBDatabase::PREEMPTIVE_TASK,
+ base::Bind(&IndexedDBDatabase::SetIndexesReadyOperation,
+ this,
+ index_ids.size()));
}
-void SetIndexesReadyOperation::Perform(IndexedDBTransaction* transaction) {
- IDB_TRACE("SetIndexesReadyOperation");
- for (size_t i = 0; i < index_count_; ++i)
+void IndexedDBDatabase::SetIndexesReadyOperation(
+ size_t index_count,
+ IndexedDBTransaction* transaction) {
+ IDB_TRACE("IndexedDBDatabase::SetIndexesReadyOperation");
+ for (size_t i = 0; i < index_count; ++i)
transaction->DidCompletePreemptiveEvent();
}
+struct IndexedDBDatabase::OpenCursorOperationParams {
+ OpenCursorOperationParams() {}
+ int64 object_store_id;
+ int64 index_id;
+ scoped_ptr<IndexedDBKeyRange> key_range;
+ indexed_db::CursorDirection direction;
+ indexed_db::CursorType cursor_type;
+ IndexedDBDatabase::TaskType task_type;
+ scoped_refptr<IndexedDBCallbacks> callbacks;
+
+ DISALLOW_COPY_AND_ASSIGN(OpenCursorOperationParams);
+};
+
void IndexedDBDatabase::OpenCursor(
int64 transaction_id,
int64 object_store_id,
@@ -1267,66 +1003,81 @@ void IndexedDBDatabase::OpenCursor(
if (!ValidateObjectStoreIdAndOptionalIndexId(object_store_id, index_id))
return;
- transaction->ScheduleTask(new OpenCursorOperation(
- backing_store_,
- id(),
- object_store_id,
- index_id,
- key_range.Pass(),
- direction,
- key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE,
- task_type,
- callbacks));
-}
-
-void OpenCursorOperation::Perform(IndexedDBTransaction* transaction) {
- IDB_TRACE("OpenCursorOperation");
+ scoped_ptr<OpenCursorOperationParams> params(new OpenCursorOperationParams());
+ params->object_store_id = object_store_id;
+ params->index_id = index_id;
+ params->key_range = key_range.Pass();
+ params->direction = direction;
+ params->cursor_type =
+ key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE;
+ params->task_type = task_type;
+ params->callbacks = callbacks;
+ transaction->ScheduleTask(base::Bind(
+ &IndexedDBDatabase::OpenCursorOperation, this, base::Passed(&params)));
+}
+
+void IndexedDBDatabase::OpenCursorOperation(
+ scoped_ptr<OpenCursorOperationParams> params,
+ IndexedDBTransaction* transaction) {
+ IDB_TRACE("IndexedDBDatabase::OpenCursorOperation");
// The frontend has begun indexing, so this pauses the transaction
// until the indexing is complete. This can't happen any earlier
// because we don't want to switch to early mode in case multiple
// indexes are being created in a row, with Put()'s in between.
- if (task_type_ == IndexedDBDatabase::PREEMPTIVE_TASK)
+ if (params->task_type == IndexedDBDatabase::PREEMPTIVE_TASK)
transaction->AddPreemptiveEvent();
scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
- if (index_id_ == IndexedDBIndexMetadata::kInvalidId) {
- DCHECK_NE(cursor_type_, indexed_db::CURSOR_KEY_ONLY);
- backing_store_cursor = backing_store_->OpenObjectStoreCursor(
- transaction->BackingStoreTransaction(),
- database_id_,
- object_store_id_,
- *key_range_,
- direction_);
+ if (params->index_id == IndexedDBIndexMetadata::kInvalidId) {
+ if (params->cursor_type == indexed_db::CURSOR_KEY_ONLY) {
+ DCHECK_EQ(params->task_type, IndexedDBDatabase::NORMAL_TASK);
+ backing_store_cursor = backing_store_->OpenObjectStoreKeyCursor(
+ transaction->BackingStoreTransaction(),
+ id(),
+ params->object_store_id,
+ *params->key_range,
+ params->direction);
+ } else {
+ backing_store_cursor = backing_store_->OpenObjectStoreCursor(
+ transaction->BackingStoreTransaction(),
+ id(),
+ params->object_store_id,
+ *params->key_range,
+ params->direction);
+ }
} else {
- DCHECK_EQ(task_type_, IndexedDBDatabase::NORMAL_TASK);
- if (cursor_type_ == indexed_db::CURSOR_KEY_ONLY) {
+ DCHECK_EQ(params->task_type, IndexedDBDatabase::NORMAL_TASK);
+ if (params->cursor_type == indexed_db::CURSOR_KEY_ONLY) {
backing_store_cursor = backing_store_->OpenIndexKeyCursor(
transaction->BackingStoreTransaction(),
- database_id_,
- object_store_id_,
- index_id_,
- *key_range_,
- direction_);
+ id(),
+ params->object_store_id,
+ params->index_id,
+ *params->key_range,
+ params->direction);
} else {
backing_store_cursor = backing_store_->OpenIndexCursor(
transaction->BackingStoreTransaction(),
- database_id_,
- object_store_id_,
- index_id_,
- *key_range_,
- direction_);
+ id(),
+ params->object_store_id,
+ params->index_id,
+ *params->key_range,
+ params->direction);
}
}
if (!backing_store_cursor) {
- callbacks_->OnSuccess(static_cast<std::string*>(NULL));
+ params->callbacks->OnSuccess(static_cast<std::string*>(NULL));
return;
}
- scoped_refptr<IndexedDBCursor> cursor = new IndexedDBCursor(
- backing_store_cursor.Pass(), cursor_type_, task_type_, transaction);
- callbacks_->OnSuccess(
+ scoped_refptr<IndexedDBCursor> cursor =
+ new IndexedDBCursor(backing_store_cursor.Pass(),
+ params->cursor_type,
+ params->task_type,
+ transaction);
+ params->callbacks->OnSuccess(
cursor, cursor->key(), cursor->primary_key(), cursor->Value());
}
@@ -1343,37 +1094,42 @@ void IndexedDBDatabase::Count(int64 transaction_id,
if (!ValidateObjectStoreIdAndOptionalIndexId(object_store_id, index_id))
return;
- transaction->ScheduleTask(new CountOperation(backing_store_,
- id(),
- object_store_id,
- index_id,
- key_range.Pass(),
- callbacks));
+ transaction->ScheduleTask(base::Bind(&IndexedDBDatabase::CountOperation,
+ this,
+ object_store_id,
+ index_id,
+ base::Passed(&key_range),
+ callbacks));
}
-void CountOperation::Perform(IndexedDBTransaction* transaction) {
- IDB_TRACE("CountOperation");
+void IndexedDBDatabase::CountOperation(
+ int64 object_store_id,
+ int64 index_id,
+ scoped_ptr<IndexedDBKeyRange> key_range,
+ scoped_refptr<IndexedDBCallbacks> callbacks,
+ IndexedDBTransaction* transaction) {
+ IDB_TRACE("IndexedDBDatabase::CountOperation");
uint32 count = 0;
scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
- if (index_id_ == IndexedDBIndexMetadata::kInvalidId) {
+ if (index_id == IndexedDBIndexMetadata::kInvalidId) {
backing_store_cursor = backing_store_->OpenObjectStoreKeyCursor(
transaction->BackingStoreTransaction(),
- database_id_,
- object_store_id_,
- *key_range_,
+ id(),
+ object_store_id,
+ *key_range,
indexed_db::CURSOR_NEXT);
} else {
backing_store_cursor = backing_store_->OpenIndexKeyCursor(
transaction->BackingStoreTransaction(),
- database_id_,
- object_store_id_,
- index_id_,
- *key_range_,
+ id(),
+ object_store_id,
+ index_id,
+ *key_range,
indexed_db::CURSOR_NEXT);
}
if (!backing_store_cursor) {
- callbacks_->OnSuccess(count);
+ callbacks->OnSuccess(count);
return;
}
@@ -1381,7 +1137,7 @@ void CountOperation::Perform(IndexedDBTransaction* transaction) {
++count;
} while (backing_store_cursor->Continue());
- callbacks_->OnSuccess(count);
+ callbacks->OnSuccess(count);
}
void IndexedDBDatabase::DeleteRange(
@@ -1398,27 +1154,34 @@ void IndexedDBDatabase::DeleteRange(
if (!ValidateObjectStoreId(object_store_id))
return;
- transaction->ScheduleTask(new DeleteRangeOperation(
- backing_store_, id(), object_store_id, key_range.Pass(), callbacks));
+ transaction->ScheduleTask(base::Bind(&IndexedDBDatabase::DeleteRangeOperation,
+ this,
+ object_store_id,
+ base::Passed(&key_range),
+ callbacks));
}
-void DeleteRangeOperation::Perform(IndexedDBTransaction* transaction) {
- IDB_TRACE("DeleteRangeOperation");
+void IndexedDBDatabase::DeleteRangeOperation(
+ int64 object_store_id,
+ scoped_ptr<IndexedDBKeyRange> key_range,
+ scoped_refptr<IndexedDBCallbacks> callbacks,
+ IndexedDBTransaction* transaction) {
+ IDB_TRACE("IndexedDBDatabase::DeleteRangeOperation");
scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor =
backing_store_->OpenObjectStoreCursor(
transaction->BackingStoreTransaction(),
- database_id_,
- object_store_id_,
- *key_range_,
+ id(),
+ object_store_id,
+ *key_range,
indexed_db::CURSOR_NEXT);
if (backing_store_cursor) {
do {
if (!backing_store_->DeleteRecord(
transaction->BackingStoreTransaction(),
- database_id_,
- object_store_id_,
+ id(),
+ object_store_id,
backing_store_cursor->record_identifier())) {
- callbacks_->OnError(
+ callbacks->OnError(
IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
"Internal error deleting data in range"));
return;
@@ -1426,7 +1189,7 @@ void DeleteRangeOperation::Perform(IndexedDBTransaction* transaction) {
} while (backing_store_cursor->Continue());
}
- callbacks_->OnSuccess();
+ callbacks->OnSuccess();
}
void IndexedDBDatabase::Clear(int64 transaction_id,
@@ -1441,64 +1204,70 @@ void IndexedDBDatabase::Clear(int64 transaction_id,
if (!ValidateObjectStoreId(object_store_id))
return;
- transaction->ScheduleTask(
- new ClearOperation(backing_store_, id(), object_store_id, callbacks));
+ transaction->ScheduleTask(base::Bind(
+ &IndexedDBDatabase::ClearOperation, this, object_store_id, callbacks));
}
-void ClearOperation::Perform(IndexedDBTransaction* transaction) {
- IDB_TRACE("ObjectStoreClearOperation");
- if (!backing_store_->ClearObjectStore(transaction->BackingStoreTransaction(),
- database_id_,
- object_store_id_)) {
- callbacks_->OnError(
+void IndexedDBDatabase::ClearOperation(
+ int64 object_store_id,
+ scoped_refptr<IndexedDBCallbacks> callbacks,
+ IndexedDBTransaction* transaction) {
+ IDB_TRACE("IndexedDBDatabase::ObjectStoreClearOperation");
+ if (!backing_store_->ClearObjectStore(
+ transaction->BackingStoreTransaction(), id(), object_store_id)) {
+ callbacks->OnError(
IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
"Internal error clearing object store"));
return;
}
- callbacks_->OnSuccess();
+ callbacks->OnSuccess();
}
-void DeleteObjectStoreOperation::Perform(IndexedDBTransaction* transaction) {
- IDB_TRACE("DeleteObjectStoreOperation");
+void IndexedDBDatabase::DeleteObjectStoreOperation(
+ const IndexedDBObjectStoreMetadata& object_store_metadata,
+ IndexedDBTransaction* transaction) {
+ IDB_TRACE("IndexedDBDatabase::DeleteObjectStoreOperation");
bool ok =
backing_store_->DeleteObjectStore(transaction->BackingStoreTransaction(),
transaction->database()->id(),
- object_store_metadata_.id);
+ object_store_metadata.id);
if (!ok) {
string16 error_string =
ASCIIToUTF16("Internal error deleting object store '") +
- object_store_metadata_.name + ASCIIToUTF16("'.");
+ object_store_metadata.name + ASCIIToUTF16("'.");
transaction->Abort(IndexedDBDatabaseError(
WebKit::WebIDBDatabaseExceptionUnknownError, error_string));
}
}
-void IndexedDBDatabase::VersionChangeOperation::Perform(
+void IndexedDBDatabase::VersionChangeOperation(
+ int64 version,
+ scoped_refptr<IndexedDBCallbacks> callbacks,
+ scoped_ptr<IndexedDBConnection> connection,
+ WebKit::WebIDBCallbacks::DataLoss data_loss,
IndexedDBTransaction* transaction) {
- IDB_TRACE("VersionChangeOperation");
- int64 database_id = database_->id();
- int64 old_version = database_->metadata_.int_version;
- DCHECK_GT(version_, old_version);
- database_->metadata_.int_version = version_;
- if (!database_->backing_store_->UpdateIDBDatabaseIntVersion(
+ IDB_TRACE("IndexedDBDatabase::VersionChangeOperation");
+ int64 old_version = metadata_.int_version;
+ DCHECK_GT(version, old_version);
+ metadata_.int_version = version;
+ if (!backing_store_->UpdateIDBDatabaseIntVersion(
transaction->BackingStoreTransaction(),
- database_id,
- database_->metadata_.int_version)) {
+ id(),
+ metadata_.int_version)) {
IndexedDBDatabaseError error(
WebKit::WebIDBDatabaseExceptionUnknownError,
ASCIIToUTF16(
"Internal error writing data to stable storage when "
"updating version."));
- callbacks_->OnError(error);
+ callbacks->OnError(error);
transaction->Abort(error);
return;
}
- DCHECK(!database_->pending_second_half_open_);
-
- database_->pending_second_half_open_.reset(new PendingSuccessCall(
- callbacks_, connection_.get(), transaction_id_, version_));
- callbacks_->OnUpgradeNeeded(
- old_version, connection_.Pass(), database_->metadata(), data_loss_);
+ DCHECK(!pending_second_half_open_);
+ pending_second_half_open_.reset(new PendingSuccessCall(
+ callbacks, connection.get(), transaction->id(), version));
+ callbacks->OnUpgradeNeeded(
+ old_version, connection.Pass(), metadata(), data_loss);
}
void IndexedDBDatabase::TransactionStarted(IndexedDBTransaction* transaction) {
@@ -1545,8 +1314,8 @@ void IndexedDBDatabase::TransactionFinishedAndCompleteFired(
// Connection was already minted for OnUpgradeNeeded callback.
scoped_ptr<IndexedDBConnection> connection;
- pending_second_half_open_->Callbacks()->OnSuccess(
- connection.Pass(), this->metadata());
+ pending_second_half_open_->Callbacks()->OnSuccess(connection.Pass(),
+ this->metadata());
pending_second_half_open_.reset();
}
ProcessPendingCalls();
@@ -1630,6 +1399,9 @@ void IndexedDBDatabase::CreateTransaction(
uint16 mode) {
DCHECK(connections_.has(connection));
+ DCHECK(transactions_.find(transaction_id) == transactions_.end());
+ if (transactions_.find(transaction_id) != transactions_.end())
+ return;
scoped_refptr<IndexedDBTransaction> transaction = new IndexedDBTransaction(
transaction_id,
@@ -1637,7 +1409,6 @@ void IndexedDBDatabase::CreateTransaction(
std::set<int64>(object_store_ids.begin(), object_store_ids.end()),
static_cast<indexed_db::TransactionMode>(mode),
this);
- DCHECK(transactions_.find(transaction_id) == transactions_.end());
transactions_[transaction_id] = transaction;
}
@@ -1765,8 +1536,8 @@ void IndexedDBDatabase::RunVersionChangeTransaction(
it != connections_.end();
++it) {
if (*it != connection.get()) {
- (*it)->callbacks()->OnVersionChange(
- metadata_.int_version, requested_version);
+ (*it)->callbacks()->OnVersionChange(metadata_.int_version,
+ requested_version);
}
}
// TODO(jsbell): Remove the call to OnBlocked and instead wait
@@ -1816,14 +1587,16 @@ void IndexedDBDatabase::RunVersionChangeTransactionFinal(
transactions_[transaction_id];
transaction->ScheduleTask(
- new VersionChangeOperation(this,
- transaction_id,
- requested_version,
- callbacks,
- connection.Pass(),
- data_loss),
- new VersionChangeAbortOperation(
- this, metadata_.version, metadata_.int_version));
+ base::Bind(&IndexedDBDatabase::VersionChangeOperation,
+ this,
+ requested_version,
+ callbacks,
+ base::Passed(&connection),
+ data_loss),
+ base::Bind(&IndexedDBDatabase::VersionChangeAbortOperation,
+ this,
+ metadata_.version,
+ metadata_.int_version));
DCHECK(!pending_second_half_open_);
}
@@ -1925,27 +1698,31 @@ void IndexedDBDatabase::Close(IndexedDBConnection* connection) {
}
}
-void CreateObjectStoreAbortOperation::Perform(
+void IndexedDBDatabase::CreateObjectStoreAbortOperation(
+ int64 object_store_id,
IndexedDBTransaction* transaction) {
- IDB_TRACE("CreateObjectStoreAbortOperation");
+ IDB_TRACE("IndexedDBDatabase::CreateObjectStoreAbortOperation");
DCHECK(!transaction);
- database_->RemoveObjectStore(object_store_id_);
+ RemoveObjectStore(object_store_id);
}
-void DeleteObjectStoreAbortOperation::Perform(
+void IndexedDBDatabase::DeleteObjectStoreAbortOperation(
+ const IndexedDBObjectStoreMetadata& object_store_metadata,
IndexedDBTransaction* transaction) {
- IDB_TRACE("DeleteObjectStoreAbortOperation");
+ IDB_TRACE("IndexedDBDatabase::DeleteObjectStoreAbortOperation");
DCHECK(!transaction);
- database_->AddObjectStore(object_store_metadata_,
- IndexedDBObjectStoreMetadata::kInvalidId);
+ AddObjectStore(object_store_metadata,
+ IndexedDBObjectStoreMetadata::kInvalidId);
}
-void IndexedDBDatabase::VersionChangeAbortOperation::Perform(
+void IndexedDBDatabase::VersionChangeAbortOperation(
+ const string16& previous_version,
+ int64 previous_int_version,
IndexedDBTransaction* transaction) {
- IDB_TRACE("VersionChangeAbortOperation");
+ IDB_TRACE("IndexedDBDatabase::VersionChangeAbortOperation");
DCHECK(!transaction);
- database_->metadata_.version = previous_version_;
- database_->metadata_.int_version = previous_int_version_;
+ metadata_.version = previous_version;
+ metadata_.int_version = previous_int_version;
}
} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_database.h b/chromium/content/browser/indexed_db/indexed_db_database.h
index 9c617f5ec63..da7039cc797 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database.h
+++ b/chromium/content/browser/indexed_db/indexed_db_database.h
@@ -52,7 +52,7 @@ class CONTENT_EXPORT IndexedDBDatabase
static scoped_refptr<IndexedDBDatabase> Create(
const string16& name,
- IndexedDBBackingStore* database,
+ IndexedDBBackingStore* backing_store,
IndexedDBFactory* factory,
const Identifier& unique_identifier);
scoped_refptr<IndexedDBBackingStore> BackingStore() const;
@@ -173,14 +173,72 @@ class CONTENT_EXPORT IndexedDBDatabase
// Number of pending deletes, blocked on other connections.
size_t PendingDeleteCount() const;
+ // Asynchronous tasks scheduled within transactions:
+ void CreateObjectStoreOperation(
+ const IndexedDBObjectStoreMetadata& object_store_metadata,
+ IndexedDBTransaction* transaction);
+ void CreateObjectStoreAbortOperation(int64 object_store_id,
+ IndexedDBTransaction* transaction);
+ void DeleteObjectStoreOperation(
+ const IndexedDBObjectStoreMetadata& object_store_metadata,
+ IndexedDBTransaction* transaction);
+ void DeleteObjectStoreAbortOperation(
+ const IndexedDBObjectStoreMetadata& object_store_metadata,
+ IndexedDBTransaction* transaction);
+ void VersionChangeOperation(int64 version,
+ scoped_refptr<IndexedDBCallbacks> callbacks,
+ scoped_ptr<IndexedDBConnection> connection,
+ WebKit::WebIDBCallbacks::DataLoss data_loss,
+ IndexedDBTransaction* transaction);
+ void VersionChangeAbortOperation(const string16& previous_version,
+ int64 previous_int_version,
+ IndexedDBTransaction* transaction);
+ void CreateIndexOperation(int64 object_store_id,
+ const IndexedDBIndexMetadata& index_metadata,
+ IndexedDBTransaction* transaction);
+ void DeleteIndexOperation(int64 object_store_id,
+ const IndexedDBIndexMetadata& index_metadata,
+ IndexedDBTransaction* transaction);
+ void CreateIndexAbortOperation(int64 object_store_id,
+ int64 index_id,
+ IndexedDBTransaction* transaction);
+ void DeleteIndexAbortOperation(int64 object_store_id,
+ const IndexedDBIndexMetadata& index_metadata,
+ IndexedDBTransaction* transaction);
+ void GetOperation(int64 object_store_id,
+ int64 index_id,
+ scoped_ptr<IndexedDBKeyRange> key_range,
+ indexed_db::CursorType cursor_type,
+ scoped_refptr<IndexedDBCallbacks> callbacks,
+ IndexedDBTransaction* transaction);
+ struct PutOperationParams;
+ void PutOperation(scoped_ptr<PutOperationParams> params,
+ IndexedDBTransaction* transaction);
+ void SetIndexesReadyOperation(size_t index_count,
+ IndexedDBTransaction* transaction);
+ struct OpenCursorOperationParams;
+ void OpenCursorOperation(scoped_ptr<OpenCursorOperationParams> params,
+ IndexedDBTransaction* transaction);
+ void CountOperation(int64 object_store_id,
+ int64 index_id,
+ scoped_ptr<IndexedDBKeyRange> key_range,
+ scoped_refptr<IndexedDBCallbacks> callbacks,
+ IndexedDBTransaction* transaction);
+ void DeleteRangeOperation(int64 object_store_id,
+ scoped_ptr<IndexedDBKeyRange> key_range,
+ scoped_refptr<IndexedDBCallbacks> callbacks,
+ IndexedDBTransaction* transaction);
+ void ClearOperation(int64 object_store_id,
+ scoped_refptr<IndexedDBCallbacks> callbacks,
+ IndexedDBTransaction* transaction);
+
private:
friend class base::RefCounted<IndexedDBDatabase>;
- IndexedDBDatabase(
- const string16& name,
- IndexedDBBackingStore* database,
- IndexedDBFactory* factory,
- const Identifier& unique_identifier);
+ IndexedDBDatabase(const string16& name,
+ IndexedDBBackingStore* backing_store,
+ IndexedDBFactory* factory,
+ const Identifier& unique_identifier);
~IndexedDBDatabase();
bool IsOpenConnectionBlocked() const;
@@ -216,12 +274,6 @@ class CONTENT_EXPORT IndexedDBDatabase
bool ValidateObjectStoreIdAndNewIndexId(int64 object_store_id,
int64 index_id) const;
- class VersionChangeOperation;
-
- // When a "versionchange" transaction aborts, these restore the back-end
- // object hierarchy.
- class VersionChangeAbortOperation;
-
scoped_refptr<IndexedDBBackingStore> backing_store_;
IndexedDBDatabaseMetadata metadata_;
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 e926a9073d7..1cbc4b82a4a 100644
--- a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc
@@ -158,6 +158,19 @@ int64 IndexedDBDispatcherHost::RendererTransactionId(
return host_transaction_id & 0xffffffff;
}
+// static
+uint32 IndexedDBDispatcherHost::TransactionIdToRendererTransactionId(
+ int64 host_transaction_id) {
+ return host_transaction_id & 0xffffffff;
+}
+
+// static
+uint32 IndexedDBDispatcherHost::TransactionIdToProcessId(
+ int64 host_transaction_id) {
+ return (host_transaction_id >> 32) & 0xffffffff;
+}
+
+
IndexedDBCursor* IndexedDBDispatcherHost::GetCursorFromId(int32 ipc_cursor_id) {
DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
return cursor_dispatcher_host_->map_.Lookup(ipc_cursor_id);
@@ -463,6 +476,12 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCreateTransaction(
int64 host_transaction_id = parent_->HostTransactionId(params.transaction_id);
+ if (transaction_database_map_.find(host_transaction_id) !=
+ transaction_database_map_.end()) {
+ DLOG(ERROR) << "Duplicate host_transaction_id.";
+ return;
+ }
+
connection->database()->CreateTransaction(
host_transaction_id, connection, params.object_store_ids, params.mode);
transaction_database_map_[host_transaction_id] = params.ipc_database_id;
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 e254cadf486..66db4a7c144 100644
--- a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h
+++ b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h
@@ -71,9 +71,16 @@ class IndexedDBDispatcherHost : public BrowserMessageFilter {
IndexedDBCursor* GetCursorFromId(int32 ipc_cursor_id);
+ // These are called to map a 32-bit front-end (renderer-specific) transaction
+ // id to and from a back-end ("host") transaction id that encodes the process
+ // id in the high 32 bits. The mapping is host-specific and ids are validated.
int64 HostTransactionId(int64 transaction_id);
int64 RendererTransactionId(int64 host_transaction_id);
+ // These are called to decode a host transaction ID, for diagnostic purposes.
+ static uint32 TransactionIdToRendererTransactionId(int64 host_transaction_id);
+ static uint32 TransactionIdToProcessId(int64 host_transaction_id);
+
private:
// Friends to enable OnDestruct() delegation.
friend class BrowserThread;
diff --git a/chromium/content/browser/indexed_db/indexed_db_factory.cc b/chromium/content/browser/indexed_db/indexed_db_factory.cc
index 6b8d0c80e00..b13b704e1b2 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_factory.cc
@@ -36,9 +36,8 @@ IndexedDBFactory::~IndexedDBFactory() {}
void IndexedDBFactory::RemoveIDBDatabaseBackend(
const IndexedDBDatabase::Identifier& unique_identifier) {
- DCHECK(database_backend_map_.find(unique_identifier) !=
- database_backend_map_.end());
- database_backend_map_.erase(unique_identifier);
+ DCHECK(database_map_.find(unique_identifier) != database_map_.end());
+ database_map_.erase(unique_identifier);
}
void IndexedDBFactory::GetDatabaseNames(
@@ -48,8 +47,9 @@ void IndexedDBFactory::GetDatabaseNames(
IDB_TRACE("IndexedDBFactory::GetDatabaseNames");
// TODO(dgrogan): Plumb data_loss back to script eventually?
WebKit::WebIDBCallbacks::DataLoss data_loss;
- scoped_refptr<IndexedDBBackingStore> backing_store =
- OpenBackingStore(origin_identifier, data_directory, &data_loss);
+ bool disk_full;
+ scoped_refptr<IndexedDBBackingStore> backing_store = OpenBackingStore(
+ origin_identifier, data_directory, &data_loss, &disk_full);
if (!backing_store) {
callbacks->OnError(
IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
@@ -68,9 +68,8 @@ void IndexedDBFactory::DeleteDatabase(
const base::FilePath& data_directory) {
IDB_TRACE("IndexedDBFactory::DeleteDatabase");
IndexedDBDatabase::Identifier unique_identifier(origin_identifier, name);
- IndexedDBDatabaseMap::iterator it =
- database_backend_map_.find(unique_identifier);
- if (it != database_backend_map_.end()) {
+ IndexedDBDatabaseMap::iterator it = database_map_.find(unique_identifier);
+ if (it != database_map_.end()) {
// If there are any connections to the database, directly delete the
// database.
it->second->DeleteDatabase(callbacks);
@@ -79,35 +78,39 @@ void IndexedDBFactory::DeleteDatabase(
// TODO(dgrogan): Plumb data_loss back to script eventually?
WebKit::WebIDBCallbacks::DataLoss data_loss;
- scoped_refptr<IndexedDBBackingStore> backing_store =
- OpenBackingStore(origin_identifier, data_directory, &data_loss);
+ bool disk_full = false;
+ scoped_refptr<IndexedDBBackingStore> backing_store = OpenBackingStore(
+ origin_identifier, data_directory, &data_loss, &disk_full);
if (!backing_store) {
- callbacks->OnError(IndexedDBDatabaseError(
- WebKit::WebIDBDatabaseExceptionUnknownError,
- ASCIIToUTF16("Internal error opening backing store "
- "for indexedDB.deleteDatabase.")));
+ callbacks->OnError(
+ IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
+ ASCIIToUTF16(
+ "Internal error opening backing store "
+ "for indexedDB.deleteDatabase.")));
return;
}
- scoped_refptr<IndexedDBDatabase> database_backend =
+ scoped_refptr<IndexedDBDatabase> database =
IndexedDBDatabase::Create(name, backing_store, this, unique_identifier);
- if (!database_backend) {
+ if (!database) {
callbacks->OnError(IndexedDBDatabaseError(
WebKit::WebIDBDatabaseExceptionUnknownError,
- ASCIIToUTF16("Internal error creating database backend for "
- "indexedDB.deleteDatabase.")));
+ ASCIIToUTF16(
+ "Internal error creating database backend for "
+ "indexedDB.deleteDatabase.")));
return;
}
- database_backend_map_[unique_identifier] = database_backend;
- database_backend->DeleteDatabase(callbacks);
- database_backend_map_.erase(unique_identifier);
+ database_map_[unique_identifier] = database;
+ database->DeleteDatabase(callbacks);
+ database_map_.erase(unique_identifier);
}
scoped_refptr<IndexedDBBackingStore> IndexedDBFactory::OpenBackingStore(
const std::string& origin_identifier,
const base::FilePath& data_directory,
- WebKit::WebIDBCallbacks::DataLoss* data_loss) {
+ WebKit::WebIDBCallbacks::DataLoss* data_loss,
+ bool* disk_full) {
const std::string file_identifier = ComputeFileIdentifier(origin_identifier);
const bool open_in_memory = data_directory.empty();
@@ -120,8 +123,11 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBFactory::OpenBackingStore(
if (open_in_memory) {
backing_store = IndexedDBBackingStore::OpenInMemory(file_identifier);
} else {
- backing_store = IndexedDBBackingStore::Open(
- origin_identifier, data_directory, file_identifier, data_loss);
+ backing_store = IndexedDBBackingStore::Open(origin_identifier,
+ data_directory,
+ file_identifier,
+ data_loss,
+ disk_full);
}
if (backing_store.get()) {
@@ -150,16 +156,24 @@ void IndexedDBFactory::Open(
const std::string& origin_identifier,
const base::FilePath& data_directory) {
IDB_TRACE("IndexedDBFactory::Open");
- scoped_refptr<IndexedDBDatabase> database_backend;
+ scoped_refptr<IndexedDBDatabase> database;
IndexedDBDatabase::Identifier unique_identifier(origin_identifier, name);
- IndexedDBDatabaseMap::iterator it =
- database_backend_map_.find(unique_identifier);
+ IndexedDBDatabaseMap::iterator it = database_map_.find(unique_identifier);
WebKit::WebIDBCallbacks::DataLoss data_loss =
WebKit::WebIDBCallbacks::DataLossNone;
- if (it == database_backend_map_.end()) {
- scoped_refptr<IndexedDBBackingStore> backing_store =
- OpenBackingStore(origin_identifier, data_directory, &data_loss);
+ bool disk_full = false;
+ if (it == database_map_.end()) {
+ scoped_refptr<IndexedDBBackingStore> backing_store = OpenBackingStore(
+ origin_identifier, data_directory, &data_loss, &disk_full);
if (!backing_store) {
+ if (disk_full) {
+ callbacks->OnError(
+ IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionQuotaError,
+ ASCIIToUTF16(
+ "Encountered full disk while opening "
+ "backing store for indexedDB.open.")));
+ return;
+ }
callbacks->OnError(IndexedDBDatabaseError(
WebKit::WebIDBDatabaseExceptionUnknownError,
ASCIIToUTF16(
@@ -167,9 +181,9 @@ void IndexedDBFactory::Open(
return;
}
- database_backend =
+ database =
IndexedDBDatabase::Create(name, backing_store, this, unique_identifier);
- if (!database_backend) {
+ if (!database) {
callbacks->OnError(IndexedDBDatabaseError(
WebKit::WebIDBDatabaseExceptionUnknownError,
ASCIIToUTF16(
@@ -177,20 +191,21 @@ void IndexedDBFactory::Open(
return;
}
- database_backend_map_[unique_identifier] = database_backend;
+ database_map_[unique_identifier] = database;
} else {
- database_backend = it->second;
+ database = it->second;
}
- database_backend->OpenConnection(
+ database->OpenConnection(
callbacks, database_callbacks, transaction_id, version, data_loss);
}
std::vector<IndexedDBDatabase*> IndexedDBFactory::GetOpenDatabasesForOrigin(
const std::string& origin_identifier) const {
std::vector<IndexedDBDatabase*> result;
- for (IndexedDBDatabaseMap::const_iterator it = database_backend_map_.begin();
- it != database_backend_map_.end(); ++it) {
+ for (IndexedDBDatabaseMap::const_iterator it = database_map_.begin();
+ it != database_map_.end();
+ ++it) {
if (it->first.first == origin_identifier)
result.push_back(it->second.get());
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_factory.h b/chromium/content/browser/indexed_db/indexed_db_factory.h
index 1666af5e49c..cea2c726f2b 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory.h
+++ b/chromium/content/browser/indexed_db/indexed_db_factory.h
@@ -16,7 +16,6 @@
#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/browser/indexed_db/indexed_db_factory.h"
#include "content/common/content_export.h"
namespace content {
@@ -57,15 +56,16 @@ class CONTENT_EXPORT IndexedDBFactory
virtual ~IndexedDBFactory();
- scoped_refptr<IndexedDBBackingStore> OpenBackingStore(
+ virtual scoped_refptr<IndexedDBBackingStore> OpenBackingStore(
const std::string& origin_identifier,
const base::FilePath& data_directory,
- WebKit::WebIDBCallbacks::DataLoss* data_loss);
+ WebKit::WebIDBCallbacks::DataLoss* data_loss,
+ bool* disk_full);
private:
typedef std::map<IndexedDBDatabase::Identifier,
scoped_refptr<IndexedDBDatabase> > IndexedDBDatabaseMap;
- IndexedDBDatabaseMap database_backend_map_;
+ IndexedDBDatabaseMap database_map_;
typedef std::map<std::string, base::WeakPtr<IndexedDBBackingStore> >
IndexedDBBackingStoreMap;
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 a5c90c4117f..230b7887552 100644
--- a/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc
@@ -257,9 +257,6 @@ void IndexedDBInternalsUI::ForceCloseOriginOnIndexedDBThread(
void IndexedDBInternalsUI::OnForcedClose(const base::FilePath& partition_path,
const GURL& origin_url,
size_t connection_count) {
-
- scoped_refptr<IndexedDBContextImpl> context;
-
web_ui()->CallJavascriptFunction(
"indexeddb.onForcedClose",
base::StringValue(partition_path.value()),
@@ -281,7 +278,7 @@ void IndexedDBInternalsUI::OnDownloadDataReady(
DownloadUrlParameters::FromWebContents(web_ui()->GetWebContents(), url));
DownloadManager* dlm = BrowserContext::GetDownloadManager(browser_context);
- const GURL referrer(web_ui()->GetWebContents()->GetURL());
+ const GURL referrer(web_ui()->GetWebContents()->GetLastCommittedURL());
dl_params->set_referrer(
content::Referrer(referrer, WebKit::WebReferrerPolicyDefault));
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 0086b82390a..3a7028012a3 100644
--- a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc
@@ -14,139 +14,137 @@
#include "content/common/indexed_db/indexed_db_key.h"
#include "content/common/indexed_db/indexed_db_key_path.h"
+// LevelDB Coding Scheme
+// =====================
+//
// LevelDB stores key/value pairs. Keys and values are strings of bytes,
// normally of type std::string.
//
-// The keys in the backing store are variable-length tuples with different types
-// of fields. Each key in the backing store starts with a ternary prefix:
-// (database id, object store id, index id). For each, 0 is reserved for
-// meta-data.
+// The keys in the backing store are variable-length tuples with different
+// types of fields. Each key in the backing store starts with a ternary
+// prefix: (database id, object store id, index id). For each, 0 is reserved
+// for metadata. See KeyPrefix::Decode() for details of the prefix coding.
+//
// The prefix makes sure that data for a specific database, object store, and
-// index are grouped together. The locality is important for performance: common
-// operations should only need a minimal number of seek operations. For example,
-// all the meta-data for a database is grouped together so that reading that
-// meta-data only requires one seek.
+// index are grouped together. The locality is important for performance:
+// common operations should only need a minimal number of seek operations. For
+// example, all the metadata for a database is grouped together so that
+// reading that metadata only requires one seek.
//
// Each key type has a class (in square brackets below) which knows how to
// encode, decode, and compare that key type.
//
-// Global meta-data have keys with prefix (0,0,0), followed by a type byte:
-//
-// <0, 0, 0, 0> =>
-// IndexedDB/LevelDB schema version [SchemaVersionKey]
-// <0, 0, 0, 1> => The maximum
-// database id ever allocated [MaxDatabaseIdKey]
-// <0, 0, 0, 2> =>
-// SerializedScriptValue version [DataVersionKey]
-// <0, 0, 0, 100, database id> => Existence
-// implies the database id is in the free list [DatabaseFreeListKey]
-// <0, 0, 0, 201, utf16 origin name, utf16 database name> => Database id
-// [DatabaseNameKey]
-//
-//
-// Database meta-data:
+// Strings (origins, names, etc) are encoded as UTF-16BE.
//
-// Again, the prefix is followed by a type byte.
//
-// <database id, 0, 0, 0> => utf16 origin name [DatabaseMetaDataKey]
-// <database id, 0, 0, 1> => utf16 database name [DatabaseMetaDataKey]
-// <database id, 0, 0, 2> => utf16 user version data [DatabaseMetaDataKey]
-// <database id, 0, 0, 3> => maximum object store id ever allocated
-// [DatabaseMetaDataKey]
-// <database id, 0, 0, 4> => user integer version (var int)
-// [DatabaseMetaDataKey]
+// Global metadata
+// ---------------
+// The prefix is <0, 0, 0>, followed by a metadata type byte:
//
+// <0, 0, 0, 0> => backing store schema version [SchemaVersionKey]
+// <0, 0, 0, 1> => maximum allocated database [MaxDatabaseIdKey]
+// <0, 0, 0, 2> => SerializedScriptValue version [DataVersionKey]
+// <0, 0, 0, 100, database id>
+// => Existence implies the database id is in the free list
+// [DatabaseFreeListKey]
+// <0, 0, 0, 201, origin, database name> => Database id [DatabaseNameKey]
//
-// Object store meta-data:
//
-// The prefix is followed by a type byte, then a variable-length integer,
-// and then another type byte.
+// Database metadata: [DatabaseMetaDataKey]
+// ----------------------------------------
+// The prefix is <database id, 0, 0> followed by a metadata type byte:
//
-// <database id, 0, 0, 50, object store id, 0> => utf16 object store name
-// [ObjectStoreMetaDataKey]
-// <database id, 0, 0, 50, object store id, 1> => utf16 key path
-// [ObjectStoreMetaDataKey]
-// <database id, 0, 0, 50, object store id, 2> => has auto increment
-// [ObjectStoreMetaDataKey]
-// <database id, 0, 0, 50, object store id, 3> => is evictable
-// [ObjectStoreMetaDataKey]
-// <database id, 0, 0, 50, object store id, 4> => last "version" number
-// [ObjectStoreMetaDataKey]
-// <database id, 0, 0, 50, object store id, 5> => maximum index id ever
-// allocated [ObjectStoreMetaDataKey]
-// <database id, 0, 0, 50, object store id, 6> => has key path (vs. null)
-// [ObjectStoreMetaDataKey]
-// <database id, 0, 0, 50, object store id, 7> => key generator current
-// number [ObjectStoreMetaDataKey]
+// <database id, 0, 0, 0> => origin name
+// <database id, 0, 0, 1> => database name
+// <database id, 0, 0, 2> => IDB string version data (obsolete)
+// <database id, 0, 0, 3> => maximum allocated object store id
+// <database id, 0, 0, 4> => IDB integer version (var int)
//
//
-// Index meta-data:
+// Object store metadata: [ObjectStoreMetaDataKey]
+// -----------------------------------------------
+// The prefix is <database id, 0, 0>, followed by a type byte (50), then the
+// object store id (var int), then a metadata type byte.
//
-// The prefix is followed by a type byte, then two variable-length integers,
-// and then another type byte.
+// <database id, 0, 0, 50, object store id, 0> => object store name
+// <database id, 0, 0, 50, object store id, 1> => key path
+// <database id, 0, 0, 50, object store id, 2> => auto increment flag
+// <database id, 0, 0, 50, object store id, 3> => is evictable
+// <database id, 0, 0, 50, object store id, 4> => last "version" number
+// <database id, 0, 0, 50, object store id, 5> => maximum allocated index id
+// <database id, 0, 0, 50, object store id, 6> => has key path flag (obsolete)
+// <database id, 0, 0, 50, object store id, 7> => key generator current number
//
-// <database id, 0, 0, 100, object store id, index id, 0> => utf16 index
-// name [IndexMetaDataKey]
-// <database id, 0, 0, 100, object store id, index id, 1> => are index keys
-// unique [IndexMetaDataKey]
-// <database id, 0, 0, 100, object store id, index id, 2> => utf16 key path
-// [IndexMetaDataKey]
-// <database id, 0, 0, 100, object store id, index id, 3> => is index
-// multi-entry [IndexMetaDataKey]
+// The key path was originally just a string (#1) or null (identified by flag,
+// #6). To support null, string, or array the coding is now identified by the
+// leading bytes in #1 - see EncodeIDBKeyPath.
//
+// The "version" field is used to weed out stale index data. Whenever new
+// object store data is inserted, it gets a new "version" number, and new
+// index data is written with this number. When the index is used for
+// look-ups, entries are validated against the "exists" entries, and records
+// with old "version" numbers are deleted when they are encountered in
+// GetPrimaryKeyViaIndex, IndexCursorImpl::LoadCurrentRow and
+// IndexKeyCursorImpl::LoadCurrentRow.
//
-// Other object store and index meta-data:
//
-// The prefix is followed by a type byte. The object store and index id are
-// variable length integers, the utf16 strings are variable length strings.
+// Index metadata: [IndexMetaDataKey]
+// ----------------------------------
+// The prefix is <database id, 0, 0>, followed by a type byte (100), then the
+// object store id (var int), then the index id (var int), then a metadata
+// type byte.
//
-// <database id, 0, 0, 150, object store id> => existence
-// implies the object store id is in the free list [ObjectStoreFreeListKey]
-// <database id, 0, 0, 151, object store id, index id> => existence
-// implies the index id is in the free list [IndexFreeListKey]
-// <database id, 0, 0, 200, utf16 object store name> => object
-// store id [ObjectStoreNamesKey]
-// <database id, 0, 0, 201, object store id, utf16 index name> => index id
-// [IndexNamesKey]
+// <database id, 0, 0, 100, object store id, index id, 0> => index name
+// <database id, 0, 0, 100, object store id, index id, 1> => unique flag
+// <database id, 0, 0, 100, object store id, index id, 2> => key path
+// <database id, 0, 0, 100, object store id, index id, 3> => multi-entry flag
//
//
-// Object store data:
+// Other object store and index metadata
+// -------------------------------------
+// The prefix is <database id, 0, 0> followed by a type byte. The object
+// store and index id are variable length integers, the names are variable
+// length strings.
//
-// The prefix is followed by a type byte. The user key is an encoded
-// IndexedDBKey.
+// <database id, 0, 0, 150, object store id>
+// => existence implies the object store id is in the free list
+// [ObjectStoreFreeListKey]
+// <database id, 0, 0, 151, object store id, index id>
+// => existence implies the index id is in the free list [IndexFreeListKey]
+// <database id, 0, 0, 200, object store name>
+// => object store id [ObjectStoreNamesKey]
+// <database id, 0, 0, 201, object store id, index name>
+// => index id [IndexNamesKey]
//
-// <database id, object store id, 1, user key> => "version", serialized
-// script value [ObjectStoreDataKey]
//
+// Object store data: [ObjectStoreDataKey]
+// ---------------------------------------
+// The prefix is followed by a type byte and the encoded IDB primary key. The
+// data has a "version" prefix followed by the serialized script value.
//
-// "Exists" entry:
+// <database id, object store id, 1, user key>
+// => "version", serialized script value
//
-// The prefix is followed by a type byte. The user key is an encoded
-// IndexedDBKey.
//
-// <database id, object store id, 2, user key> => "version" [ExistsEntryKey]
+// "Exists" entry: [ExistsEntryKey]
+// --------------------------------
+// The prefix is followed by a type byte and the encoded IDB primary key.
//
+// <database id, object store id, 2, user key> => "version"
//
-// Index data:
//
-// The prefix is followed by a type byte. The index key is an encoded
-// IndexedDBKey. The sequence number is a variable length integer.
-// The primary key is an encoded IndexedDBKey.
+// Index data
+// ----------
+// The prefix is followed by a type byte, the encoded IDB index key, a
+// "sequence" number (obsolete; var int), and the encoded IDB primary key.
//
-// <database id, object store id, index id, index key, sequence number,
-// primary key> => "version", primary key [IndexDataKey]
+// <database id, object store id, index id, index key, sequence number,
+// primary key> => "version", primary key [IndexDataKey]
//
-// (The sequence number is obsolete; it was used to allow two entries with
-// the same user (index) key in non-unique indexes prior to the inclusion of
-// the primary key in the data. The "version" field is used to weed out
-// stale
-// index data. Whenever new object store data is inserted, it gets a new
-// "version" number, and new index data is written with this number. When
-// the index is used for look-ups, entries are validated against the
-// "exists" entries, and records with old "version" numbers are deleted
-// when they are encountered in get_primary_key_via_index,
-// IndexCursorImpl::load_current_row, and
-// IndexKeyCursorImpl::load_current_row).
+// The sequence number is obsolete; it was used to allow two entries with the
+// same user (index) key in non-unique indexes prior to the inclusion of the
+// primary key in the data.
+
using base::StringPiece;
using WebKit::WebIDBKeyType;
@@ -675,11 +673,21 @@ static int CompareInts(int64 a, int64 b) {
return 0;
}
+static inline int CompareSizes(size_t a, size_t b) {
+ if (a > b)
+ return 1;
+ if (b > a)
+ return -1;
+ return 0;
+}
+
static int CompareTypes(WebIDBKeyType a, WebIDBKeyType b) { return b - a; }
int CompareEncodedIDBKeys(StringPiece* slice_a,
StringPiece* slice_b,
bool* ok) {
+ DCHECK(!slice_a->empty());
+ DCHECK(!slice_b->empty());
*ok = true;
unsigned char type_a = (*slice_a)[0];
unsigned char type_b = (*slice_b)[0];
@@ -744,7 +752,10 @@ int CompareEncodedIDBKeys(const std::string& key_a,
namespace {
template <typename KeyType>
-int Compare(const StringPiece& a, const StringPiece& b, bool, bool* ok) {
+int Compare(const StringPiece& a,
+ const StringPiece& b,
+ bool only_compare_index_keys,
+ bool* ok) {
KeyType key_a;
KeyType key_b;
@@ -763,10 +774,29 @@ int Compare(const StringPiece& a, const StringPiece& b, bool, bool* ok) {
return key_a.Compare(key_b);
}
+template <typename KeyType>
+int CompareSuffix(StringPiece* a,
+ StringPiece* b,
+ bool only_compare_index_keys,
+ bool* ok) {
+ NOTREACHED();
+ return 0;
+}
+
+template <>
+int CompareSuffix<ExistsEntryKey>(StringPiece* slice_a,
+ StringPiece* slice_b,
+ bool only_compare_index_keys,
+ bool* ok) {
+ DCHECK(!slice_a->empty());
+ DCHECK(!slice_b->empty());
+ return CompareEncodedIDBKeys(slice_a, slice_b, ok);
+}
+
template <>
int Compare<ExistsEntryKey>(const StringPiece& a,
const StringPiece& b,
- bool,
+ bool only_compare_index_keys,
bool* ok) {
KeyPrefix prefix_a;
KeyPrefix prefix_b;
@@ -787,13 +817,22 @@ int Compare<ExistsEntryKey>(const StringPiece& a,
// Prefixes are not compared - it is assumed this was already done.
DCHECK(!prefix_a.Compare(prefix_b));
- return CompareEncodedIDBKeys(&slice_a, &slice_b, ok);
+ 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,
+ bool* ok) {
+ return CompareEncodedIDBKeys(slice_a, slice_b, ok);
}
template <>
int Compare<ObjectStoreDataKey>(const StringPiece& a,
const StringPiece& b,
- bool,
+ bool only_compare_index_keys,
bool* ok) {
KeyPrefix prefix_a;
KeyPrefix prefix_b;
@@ -814,13 +853,45 @@ int Compare<ObjectStoreDataKey>(const StringPiece& a,
// Prefixes are not compared - it is assumed this was already done.
DCHECK(!prefix_a.Compare(prefix_b));
- return CompareEncodedIDBKeys(&slice_a, &slice_b, ok);
+ 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,
+ bool* ok) {
+ // index key
+ int result = CompareEncodedIDBKeys(slice_a, slice_b, ok);
+ if (!*ok || result)
+ return result;
+ if (only_compare_index_keys)
+ return 0;
+
+ // sequence number [optional]
+ int64 sequence_number_a = -1;
+ int64 sequence_number_b = -1;
+ if (!slice_a->empty() && !DecodeVarInt(slice_a, &sequence_number_a))
+ return 0;
+ if (!slice_b->empty() && !DecodeVarInt(slice_b, &sequence_number_b))
+ return 0;
+
+ if (slice_a->empty() || slice_b->empty())
+ return CompareSizes(slice_a->size(), slice_b->size());
+
+ // primary key [optional]
+ result = CompareEncodedIDBKeys(slice_a, slice_b, ok);
+ if (!*ok || result)
+ return result;
+
+ return CompareInts(sequence_number_a, sequence_number_b);
}
template <>
int Compare<IndexDataKey>(const StringPiece& a,
const StringPiece& b,
- bool ignore_duplicates,
+ bool only_compare_index_keys,
bool* ok) {
KeyPrefix prefix_a;
KeyPrefix prefix_b;
@@ -841,43 +912,13 @@ int Compare<IndexDataKey>(const StringPiece& a,
// Prefixes are not compared - it is assumed this was already done.
DCHECK(!prefix_a.Compare(prefix_b));
- // index key
- int result = CompareEncodedIDBKeys(&slice_a, &slice_b, ok);
- if (!*ok || result)
- return result;
- if (ignore_duplicates)
- return 0;
-
- // sequence number [optional]
- int64 sequence_number_a = -1;
- int64 sequence_number_b = -1;
- if (!slice_a.empty()) {
- if (!DecodeVarInt(&slice_a, &sequence_number_a))
- return 0;
- }
- if (!slice_b.empty()) {
- if (!DecodeVarInt(&slice_b, &sequence_number_b))
- return 0;
- }
-
- // primary key [optional]
- if (slice_a.empty() && slice_b.empty())
- return 0;
- if (slice_a.empty())
- return -1;
- if (slice_b.empty())
- return 1;
-
- result = CompareEncodedIDBKeys(&slice_a, &slice_b, ok);
- if (!*ok || result)
- return result;
-
- return CompareInts(sequence_number_a, sequence_number_b);
+ return CompareSuffix<IndexDataKey>(
+ &slice_a, &slice_b, only_compare_index_keys, ok);
}
int Compare(const StringPiece& a,
const StringPiece& b,
- bool index_keys,
+ bool only_compare_index_keys,
bool* ok) {
StringPiece slice_a(a);
StringPiece slice_b(b);
@@ -918,11 +959,16 @@ int Compare(const StringPiece& a,
if (type_byte_a < kMaxSimpleGlobalMetaDataTypeByte)
return 0;
- const bool ignore_duplicates = false;
+ // Compare<> is used (which re-decodes the prefix) rather than an
+ // specialized CompareSuffix<> because metadata is relatively uncommon
+ // in the database.
+
if (type_byte_a == kDatabaseFreeListTypeByte)
- return Compare<DatabaseFreeListKey>(a, b, ignore_duplicates, ok);
+ return Compare<DatabaseFreeListKey>(
+ a, b, only_compare_index_keys, ok);
if (type_byte_a == kDatabaseNameTypeByte)
- return Compare<DatabaseNameKey>(a, b, ignore_duplicates, ok);
+ return Compare<DatabaseNameKey>(
+ a, b, /*only_compare_index_keys*/ false, ok);
break;
}
@@ -947,50 +993,56 @@ int Compare(const StringPiece& a,
if (type_byte_a < DatabaseMetaDataKey::MAX_SIMPLE_METADATA_TYPE)
return 0;
- const bool ignore_duplicates = false;
+ // Compare<> is used (which re-decodes the prefix) rather than an
+ // specialized CompareSuffix<> because metadata is relatively uncommon
+ // in the database.
+
if (type_byte_a == kObjectStoreMetaDataTypeByte)
- return Compare<ObjectStoreMetaDataKey>(a, b, ignore_duplicates, ok);
+ return Compare<ObjectStoreMetaDataKey>(
+ a, b, only_compare_index_keys, ok);
if (type_byte_a == kIndexMetaDataTypeByte)
- return Compare<IndexMetaDataKey>(a, b, ignore_duplicates, ok);
+ return Compare<IndexMetaDataKey>(
+ a, b, /*only_compare_index_keys*/ false, ok);
if (type_byte_a == kObjectStoreFreeListTypeByte)
- return Compare<ObjectStoreFreeListKey>(a, b, ignore_duplicates, ok);
+ return Compare<ObjectStoreFreeListKey>(
+ a, b, only_compare_index_keys, ok);
if (type_byte_a == kIndexFreeListTypeByte)
- return Compare<IndexFreeListKey>(a, b, ignore_duplicates, ok);
+ return Compare<IndexFreeListKey>(
+ a, b, /*only_compare_index_keys*/ false, ok);
if (type_byte_a == kObjectStoreNamesTypeByte)
- return Compare<ObjectStoreNamesKey>(a, b, ignore_duplicates, ok);
+ return Compare<ObjectStoreNamesKey>(
+ a, b, only_compare_index_keys, ok);
if (type_byte_a == kIndexNamesKeyTypeByte)
- return Compare<IndexNamesKey>(a, b, ignore_duplicates, ok);
+ return Compare<IndexNamesKey>(
+ a, b, /*only_compare_index_keys*/ false, ok);
break;
}
case KeyPrefix::OBJECT_STORE_DATA: {
+ // Provide a stable ordering for invalid data.
if (slice_a.empty() || slice_b.empty())
- return slice_a.size() - slice_b.size();
- // TODO(jsbell): This case of non-existing user keys should not have to be
- // handled this way.
+ return CompareSizes(slice_a.size(), slice_b.size());
- const bool ignore_duplicates = false;
- return Compare<ObjectStoreDataKey>(a, b, ignore_duplicates, ok);
+ return CompareSuffix<ObjectStoreDataKey>(
+ &slice_a, &slice_b, /*only_compare_index_keys*/ false, ok);
}
case KeyPrefix::EXISTS_ENTRY: {
+ // Provide a stable ordering for invalid data.
if (slice_a.empty() || slice_b.empty())
- return slice_a.size() - slice_b.size();
- // TODO(jsbell): This case of non-existing user keys should not have to be
- // handled this way.
+ return CompareSizes(slice_a.size(), slice_b.size());
- const bool ignore_duplicates = false;
- return Compare<ExistsEntryKey>(a, b, ignore_duplicates, ok);
+ return CompareSuffix<ExistsEntryKey>(
+ &slice_a, &slice_b, /*only_compare_index_keys*/ false, ok);
}
case KeyPrefix::INDEX_DATA: {
+ // Provide a stable ordering for invalid data.
if (slice_a.empty() || slice_b.empty())
- return slice_a.size() - slice_b.size();
- // TODO(jsbell): This case of non-existing user keys should not have to be
- // handled this way.
+ return CompareSizes(slice_a.size(), slice_b.size());
- bool ignore_duplicates = index_keys;
- return Compare<IndexDataKey>(a, b, ignore_duplicates, ok);
+ return CompareSuffix<IndexDataKey>(
+ &slice_a, &slice_b, only_compare_index_keys, ok);
}
case KeyPrefix::INVALID_TYPE:
@@ -1004,9 +1056,11 @@ int Compare(const StringPiece& a,
} // namespace
-int Compare(const StringPiece& a, const StringPiece& b, bool index_keys) {
+int Compare(const StringPiece& a,
+ const StringPiece& b,
+ bool only_compare_index_keys) {
bool ok;
- int result = Compare(a, b, index_keys, &ok);
+ int result = Compare(a, b, only_compare_index_keys, &ok);
DCHECK(ok);
if (!ok)
return 0;
@@ -1357,10 +1411,7 @@ int ObjectStoreMetaDataKey::Compare(const ObjectStoreMetaDataKey& other) {
DCHECK_GE(object_store_id_, 0);
if (int x = CompareInts(object_store_id_, other.object_store_id_))
return x;
- int64 result = meta_data_type_ - other.meta_data_type_;
- if (result < 0)
- return -1;
- return (result > 0) ? 1 : result;
+ return meta_data_type_ - other.meta_data_type_;
}
IndexMetaDataKey::IndexMetaDataKey()
@@ -1782,7 +1833,7 @@ std::string IndexDataKey::EncodeMaxKey(int64 database_id,
}
int IndexDataKey::Compare(const IndexDataKey& other,
- bool ignore_duplicates,
+ bool only_compare_index_keys,
bool* ok) {
DCHECK_GE(database_id_, 0);
DCHECK_GE(object_store_id_, 0);
@@ -1791,7 +1842,7 @@ int IndexDataKey::Compare(const IndexDataKey& other,
CompareEncodedIDBKeys(encoded_user_key_, other.encoded_user_key_, ok);
if (!*ok || result)
return result;
- if (ignore_duplicates)
+ if (only_compare_index_keys)
return 0;
result = CompareEncodedIDBKeys(
encoded_primary_key_, other.encoded_primary_key_, ok);
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 ecd8b9b2d99..974c27a4fa2 100644
--- a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h
+++ b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h
@@ -402,7 +402,9 @@ class IndexDataKey {
CONTENT_EXPORT static std::string EncodeMaxKey(int64 database_id,
int64 object_store_id,
int64 index_id);
- int Compare(const IndexDataKey& other, bool ignore_duplicates, bool* ok);
+ 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 c9f39762438..01f1260828b 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
@@ -799,10 +799,13 @@ TEST(IndexedDBLevelDBCodingTest, ComparisonTest) {
keys.push_back(IndexNamesKey::Encode(1, 1, ASCIIToUTF16("")));
keys.push_back(IndexNamesKey::Encode(1, 1, ASCIIToUTF16("a")));
keys.push_back(IndexNamesKey::Encode(1, 2, ASCIIToUTF16("a")));
+ keys.push_back(ObjectStoreDataKey::Encode(1, 1, std::string()));
keys.push_back(ObjectStoreDataKey::Encode(1, 1, MinIDBKey()));
keys.push_back(ObjectStoreDataKey::Encode(1, 1, MaxIDBKey()));
+ keys.push_back(ExistsEntryKey::Encode(1, 1, std::string()));
keys.push_back(ExistsEntryKey::Encode(1, 1, MinIDBKey()));
keys.push_back(ExistsEntryKey::Encode(1, 1, MaxIDBKey()));
+ keys.push_back(IndexDataKey::Encode(1, 1, 30, MinIDBKey(), std::string(), 0));
keys.push_back(IndexDataKey::Encode(1, 1, 30, MinIDBKey(), MinIDBKey(), 0));
keys.push_back(IndexDataKey::Encode(1, 1, 30, MinIDBKey(), MinIDBKey(), 1));
keys.push_back(IndexDataKey::Encode(1, 1, 30, MinIDBKey(), MaxIDBKey(), 0));
diff --git a/chromium/content/browser/indexed_db/indexed_db_quota_client.cc b/chromium/content/browser/indexed_db/indexed_db_quota_client.cc
index 1b187c51339..5e0cea898e0 100644
--- a/chromium/content/browser/indexed_db/indexed_db_quota_client.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_quota_client.cc
@@ -175,4 +175,8 @@ void IndexedDBQuotaClient::DeleteOriginData(const GURL& origin,
callback);
}
+bool IndexedDBQuotaClient::DoesSupport(quota::StorageType type) const {
+ return type == quota::kStorageTypeTemporary;
+}
+
} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_quota_client.h b/chromium/content/browser/indexed_db/indexed_db_quota_client.h
index 6c0f2bb2af7..3c48c279ccf 100644
--- a/chromium/content/browser/indexed_db/indexed_db_quota_client.h
+++ b/chromium/content/browser/indexed_db/indexed_db_quota_client.h
@@ -43,6 +43,7 @@ class IndexedDBQuotaClient : public quota::QuotaClient,
virtual void DeleteOriginData(const GURL& origin,
quota::StorageType type,
const DeletionCallback& callback) OVERRIDE;
+ virtual bool DoesSupport(quota::StorageType type) const OVERRIDE;
private:
scoped_refptr<IndexedDBContextImpl> indexed_db_context_;
diff --git a/chromium/content/browser/indexed_db/indexed_db_transaction.cc b/chromium/content/browser/indexed_db/indexed_db_transaction.cc
index b096f3b3319..3916726f531 100644
--- a/chromium/content/browser/indexed_db/indexed_db_transaction.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_transaction.cc
@@ -23,15 +23,14 @@ IndexedDBTransaction::TaskQueue::~TaskQueue() { clear(); }
void IndexedDBTransaction::TaskQueue::clear() {
while (!queue_.empty())
- scoped_ptr<Operation> task(pop());
+ queue_.pop();
}
-scoped_ptr<IndexedDBTransaction::Operation>
-IndexedDBTransaction::TaskQueue::pop() {
+IndexedDBTransaction::Operation IndexedDBTransaction::TaskQueue::pop() {
DCHECK(!queue_.empty());
- scoped_ptr<Operation> task(queue_.front());
+ Operation task(queue_.front());
queue_.pop();
- return task.Pass();
+ return task;
}
IndexedDBTransaction::TaskStack::TaskStack() {}
@@ -39,15 +38,14 @@ IndexedDBTransaction::TaskStack::~TaskStack() { clear(); }
void IndexedDBTransaction::TaskStack::clear() {
while (!stack_.empty())
- scoped_ptr<Operation> task(pop());
+ stack_.pop();
}
-scoped_ptr<IndexedDBTransaction::Operation>
-IndexedDBTransaction::TaskStack::pop() {
+IndexedDBTransaction::Operation IndexedDBTransaction::TaskStack::pop() {
DCHECK(!stack_.empty());
- scoped_ptr<Operation> task(stack_.top());
+ Operation task(stack_.top());
stack_.pop();
- return task.Pass();
+ return task;
}
IndexedDBTransaction::IndexedDBTransaction(
@@ -65,7 +63,11 @@ IndexedDBTransaction::IndexedDBTransaction(
database_(database),
transaction_(database->BackingStore().get()),
should_process_queue_(false),
- pending_preemptive_events_(0) {
+ pending_preemptive_events_(0),
+ queue_status_(CREATED),
+ creation_time_(base::Time::Now()),
+ tasks_scheduled_(0),
+ tasks_completed_(0) {
database_->transaction_coordinator().DidCreateTransaction(this);
}
@@ -78,20 +80,30 @@ IndexedDBTransaction::~IndexedDBTransaction() {
DCHECK(abort_task_stack_.empty());
}
+void IndexedDBTransaction::ScheduleTask(Operation task, Operation abort_task) {
+ if (state_ == FINISHED)
+ return;
+ task_queue_.push(task);
+ ++tasks_scheduled_;
+ abort_task_stack_.push(abort_task);
+ EnsureTasksRunning();
+}
+
void IndexedDBTransaction::ScheduleTask(IndexedDBDatabase::TaskType type,
- Operation* task,
- Operation* abort_task) {
+ Operation task) {
if (state_ == FINISHED)
return;
- if (type == IndexedDBDatabase::NORMAL_TASK)
+ if (type == IndexedDBDatabase::NORMAL_TASK) {
task_queue_.push(task);
- else
+ ++tasks_scheduled_;
+ } else {
preemptive_task_queue_.push(task);
+ }
+ EnsureTasksRunning();
+}
- if (abort_task)
- abort_task_stack_.push(abort_task);
-
+void IndexedDBTransaction::EnsureTasksRunning() {
if (state_ == UNUSED) {
Start();
} else if (state_ == RUNNING && !should_process_queue_) {
@@ -126,8 +138,8 @@ void IndexedDBTransaction::Abort(const IndexedDBDatabaseError& error) {
// Run the abort tasks, if any.
while (!abort_task_stack_.empty()) {
- scoped_ptr<Operation> task(abort_task_stack_.pop());
- task->Perform(0);
+ Operation task(abort_task_stack_.pop());
+ task.Run(0);
}
preemptive_task_queue_.clear();
task_queue_.clear();
@@ -177,6 +189,7 @@ void IndexedDBTransaction::Run() {
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));
@@ -272,8 +285,12 @@ void IndexedDBTransaction::ProcessTaskQueue() {
pending_preemptive_events_ ? &preemptive_task_queue_ : &task_queue_;
while (!task_queue->empty() && state_ != FINISHED) {
DCHECK_EQ(state_, RUNNING);
- scoped_ptr<Operation> task(task_queue->pop());
- task->Perform(this);
+ Operation task(task_queue->pop());
+ task.Run(this);
+ if (!pending_preemptive_events_) {
+ DCHECK(tasks_completed_ < tasks_scheduled_);
+ ++tasks_completed_;
+ }
// Event itself may change which queue should be processed next.
task_queue =
diff --git a/chromium/content/browser/indexed_db/indexed_db_transaction.h b/chromium/content/browser/indexed_db/indexed_db_transaction.h
index 51b1c0ad2fb..24f44490537 100644
--- a/chromium/content/browser/indexed_db/indexed_db_transaction.h
+++ b/chromium/content/browser/indexed_db/indexed_db_transaction.h
@@ -12,6 +12,7 @@
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/time/time.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"
@@ -23,6 +24,8 @@ class IndexedDBDatabaseCallbacks;
class IndexedDBTransaction : public base::RefCounted<IndexedDBTransaction> {
public:
+ typedef base::Callback<void(IndexedDBTransaction*)> Operation;
+
IndexedDBTransaction(int64 id,
scoped_refptr<IndexedDBDatabaseCallbacks> callbacks,
const std::set<int64>& object_store_ids,
@@ -32,29 +35,16 @@ class IndexedDBTransaction : public base::RefCounted<IndexedDBTransaction> {
virtual void Abort();
void Commit();
- class Operation {
- public:
- Operation() {}
- virtual ~Operation() {}
- virtual void Perform(IndexedDBTransaction* transaction) = 0;
- };
-
void Abort(const IndexedDBDatabaseError& error);
void Run();
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, NULL);
- }
- void ScheduleTask(Operation* task, Operation* abort_task) {
- ScheduleTask(IndexedDBDatabase::NORMAL_TASK, task, abort_task);
- }
- void ScheduleTask(IndexedDBDatabase::TaskType task_type, Operation* task) {
- ScheduleTask(task_type, task, NULL);
+ void ScheduleTask(Operation task) {
+ ScheduleTask(IndexedDBDatabase::NORMAL_TASK, task);
}
- void ScheduleTask(IndexedDBDatabase::TaskType task_type,
- Operation* task,
- Operation* abort_task);
+
+ void ScheduleTask(Operation task, Operation abort_task);
+ void ScheduleTask(IndexedDBDatabase::TaskType, Operation task);
void RegisterOpenCursor(IndexedDBCursor* cursor);
void UnregisterOpenCursor(IndexedDBCursor* cursor);
void AddPreemptiveEvent() { pending_preemptive_events_++; }
@@ -71,6 +61,20 @@ class IndexedDBTransaction : public base::RefCounted<IndexedDBTransaction> {
IndexedDBDatabaseCallbacks* connection() const { return callbacks_; }
bool IsRunning() const { return state_ == RUNNING; }
+ // The following types/accessors are for diagnostics only.
+ enum QueueStatus {
+ CREATED,
+ BLOCKED,
+ UNBLOCKED,
+ };
+
+ 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_; }
+
protected:
virtual ~IndexedDBTransaction();
friend class base::RefCounted<IndexedDBTransaction>;
@@ -84,6 +88,7 @@ class IndexedDBTransaction : public base::RefCounted<IndexedDBTransaction> {
FINISHED, // Either aborted or committed.
};
+ void EnsureTasksRunning();
void Start();
bool IsTaskQueueEmpty() const;
@@ -106,12 +111,12 @@ class IndexedDBTransaction : public base::RefCounted<IndexedDBTransaction> {
TaskQueue();
~TaskQueue();
bool empty() const { return queue_.empty(); }
- void push(Operation* task) { queue_.push(task); }
- scoped_ptr<Operation> pop();
+ void push(Operation task) { queue_.push(task); }
+ Operation pop();
void clear();
private:
- std::queue<Operation*> queue_;
+ std::queue<Operation> queue_;
};
class TaskStack {
@@ -119,12 +124,12 @@ class IndexedDBTransaction : public base::RefCounted<IndexedDBTransaction> {
TaskStack();
~TaskStack();
bool empty() const { return stack_.empty(); }
- void push(Operation* task) { stack_.push(task); }
- scoped_ptr<Operation> pop();
+ void push(Operation task) { stack_.push(task); }
+ Operation pop();
void clear();
private:
- std::stack<Operation*> stack_;
+ std::stack<Operation> stack_;
};
TaskQueue task_queue_;
@@ -137,6 +142,13 @@ class IndexedDBTransaction : public base::RefCounted<IndexedDBTransaction> {
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_;
};
} // 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 1f5100d26ac..7be7bcafcaf 100644
--- a/chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.cc
@@ -21,6 +21,7 @@ IndexedDBTransactionCoordinator::~IndexedDBTransactionCoordinator() {
void IndexedDBTransactionCoordinator::DidCreateTransaction(
IndexedDBTransaction* transaction) {
DCHECK(transactions_.find(transaction) == transactions_.end());
+ DCHECK(transaction->queue_status() == IndexedDBTransaction::CREATED);
transactions_[transaction] = transaction;
}
@@ -92,62 +93,81 @@ void IndexedDBTransactionCoordinator::ProcessStartedTransactions() {
(*started_transactions_.begin())->mode() !=
indexed_db::TRANSACTION_VERSION_CHANGE);
+ // The locked_scope set accumulates the ids of object stores in the scope of
+ // running read/write transactions. Other read-write transactions with
+ // stores in this set may not be started. Read-only transactions may start,
+ // taking a snapshot of the database, which does not include uncommitted
+ // 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();
+ 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
+ // stores within their scopes.
+ locked_scope.insert(transaction->scope().begin(),
+ transaction->scope().end());
+ }
+ }
+
list_set<IndexedDBTransaction*>::const_iterator it =
queued_transactions_.begin();
while (it != queued_transactions_.end()) {
IndexedDBTransaction* transaction = *it;
++it;
- if (CanRunTransaction(transaction)) {
+ if (CanRunTransaction(transaction, locked_scope)) {
+ transaction->set_queue_status(IndexedDBTransaction::UNBLOCKED);
queued_transactions_.erase(transaction);
started_transactions_.insert(transaction);
transaction->Run();
+ } else {
+ transaction->set_queue_status(IndexedDBTransaction::BLOCKED);
+ }
+ if (transaction->mode() == indexed_db::TRANSACTION_READ_WRITE) {
+ // Either the transaction started, so it has exclusive access to the
+ // stores in its scope, or per the spec the transaction which was
+ // created first must get access first, so the stores are also locked.
+ locked_scope.insert(transaction->scope().begin(),
+ transaction->scope().end());
}
}
}
-static bool DoScopesOverlap(const std::set<int64>& scope1,
- const std::set<int64>& scope2) {
- for (std::set<int64>::const_iterator it = scope1.begin(); it != scope1.end();
- ++it) {
- if (scope2.find(*it) != scope2.end())
+template<typename T>
+static bool DoSetsIntersect(const std::set<T>& set1,
+ const std::set<T>& set2) {
+ typename std::set<T>::const_iterator it1 = set1.begin();
+ typename std::set<T>::const_iterator it2 = set2.begin();
+ while (it1 != set1.end() && it2 != set2.end()) {
+ if (*it1 < *it2)
+ ++it1;
+ else if (*it2 < *it1)
+ ++it2;
+ else
return true;
}
return false;
}
bool IndexedDBTransactionCoordinator::CanRunTransaction(
- IndexedDBTransaction* transaction) {
+ IndexedDBTransaction* const transaction,
+ const std::set<int64>& locked_scope) const {
DCHECK(queued_transactions_.has(transaction));
switch (transaction->mode()) {
case indexed_db::TRANSACTION_VERSION_CHANGE:
DCHECK_EQ(static_cast<size_t>(1), queued_transactions_.size());
DCHECK(started_transactions_.empty());
+ DCHECK(locked_scope.empty());
return true;
case indexed_db::TRANSACTION_READ_ONLY:
return true;
case indexed_db::TRANSACTION_READ_WRITE:
- for (list_set<IndexedDBTransaction*>::const_iterator it =
- started_transactions_.begin();
- it != started_transactions_.end();
- ++it) {
- IndexedDBTransaction* other = *it;
- if (other->mode() == indexed_db::TRANSACTION_READ_WRITE &&
- DoScopesOverlap(transaction->scope(), other->scope()))
- return false;
- }
- for (list_set<IndexedDBTransaction*>::const_iterator it =
- queued_transactions_.begin();
- *it != transaction;
- ++it) {
- DCHECK(it != queued_transactions_.end());
- IndexedDBTransaction* other = *it;
- if (other->mode() == indexed_db::TRANSACTION_READ_WRITE &&
- DoScopesOverlap(transaction->scope(), other->scope()))
- return false;
- }
- return true;
+ return !DoSetsIntersect(transaction->scope(), locked_scope);
}
NOTREACHED();
return false;
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 d9f9cd53266..e123a4e7383 100644
--- a/chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.h
+++ b/chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.h
@@ -37,7 +37,8 @@ class IndexedDBTransactionCoordinator {
private:
void ProcessStartedTransactions();
- bool CanRunTransaction(IndexedDBTransaction* transaction);
+ 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> >
diff --git a/chromium/content/browser/indexed_db/leveldb/avltree.h b/chromium/content/browser/indexed_db/leveldb/avltree.h
deleted file mode 100644
index 91df04868c7..00000000000
--- a/chromium/content/browser/indexed_db/leveldb/avltree.h
+++ /dev/null
@@ -1,977 +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.
-
-/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * Based on Abstract AVL Tree Template v1.5 by Walt Karas
- * <http://geocities.com/wkaras/gen_cpp/avl_tree.html>.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef CONTENT_BROWSER_INDEXED_DB_LEVELDB_AVLTREE_H_
-#define CONTENT_BROWSER_INDEXED_DB_LEVELDB_AVLTREE_H_
-
-#include "base/logging.h"
-#include "content/browser/indexed_db/leveldb/fixed_array.h"
-
-namespace content {
-
-// Here is the reference class for BSet.
-//
-// class BSet
-// {
-// public:
-//
-// class ANY_bitref
-// {
-// public:
-// operator bool ();
-// void operator = (bool b);
-// };
-//
-// // Does not have to initialize bits.
-// BSet();
-//
-// // Must return a valid value for index when 0 <= index < maxDepth
-// ANY_bitref operator [] (unsigned index);
-//
-// // Set all bits to 1.
-// void Set();
-//
-// // Set all bits to 0.
-// void Reset();
-// };
-
-template <unsigned maxDepth>
-class AVLTreeDefaultBSet {
- public:
- bool& operator[](unsigned i) {
-#if defined(ADDRESS_SANITIZER)
- CHECK(i < maxDepth);
-#endif
- return data_[i];
- }
- void Set() {
- for (unsigned i = 0; i < maxDepth; ++i)
- data_[i] = true;
- }
- void Reset() {
- for (unsigned i = 0; i < maxDepth; ++i)
- data_[i] = false;
- }
-
- private:
- FixedArray<bool, maxDepth> data_;
-};
-
-// How to determine maxDepth:
-// d Minimum number of nodes
-// 2 2
-// 3 4
-// 4 7
-// 5 12
-// 6 20
-// 7 33
-// 8 54
-// 9 88
-// 10 143
-// 11 232
-// 12 376
-// 13 609
-// 14 986
-// 15 1,596
-// 16 2,583
-// 17 4,180
-// 18 6,764
-// 19 10,945
-// 20 17,710
-// 21 28,656
-// 22 46,367
-// 23 75,024
-// 24 121,392
-// 25 196,417
-// 26 317,810
-// 27 514,228
-// 28 832,039
-// 29 1,346,268
-// 30 2,178,308
-// 31 3,524,577
-// 32 5,702,886
-// 33 9,227,464
-// 34 14,930,351
-// 35 24,157,816
-// 36 39,088,168
-// 37 63,245,985
-// 38 102,334,154
-// 39 165,580,140
-// 40 267,914,295
-// 41 433,494,436
-// 42 701,408,732
-// 43 1,134,903,169
-// 44 1,836,311,902
-// 45 2,971,215,072
-//
-// E.g., if, in a particular instantiation, the maximum number of nodes in a
-// tree instance is 1,000,000, the maximum depth should be 28.
-// You pick 28 because MN(28) is 832,039, which is less than or equal to
-// 1,000,000, and MN(29) is 1,346,268, which is strictly greater than 1,000,000.
-
-template <class Abstractor,
- unsigned maxDepth = 32,
- class BSet = AVLTreeDefaultBSet<maxDepth> >
-class AVLTree {
- public:
- typedef typename Abstractor::key key;
- typedef typename Abstractor::handle handle;
- typedef typename Abstractor::size size;
-
- enum SearchType {
- EQUAL = 1,
- LESS = 2,
- GREATER = 4,
- LESS_EQUAL = EQUAL | LESS,
- GREATER_EQUAL = EQUAL | GREATER
- };
-
- Abstractor& abstractor() { return abs_; }
-
- inline handle Insert(handle h);
-
- inline handle Search(key k, SearchType st = EQUAL);
- inline handle SearchLeast();
- inline handle SearchGreatest();
-
- inline handle Remove(key k);
-
- inline handle Subst(handle new_node);
-
- void Purge() { abs_.root = Null(); }
-
- bool IsEmpty() { return abs_.root == Null(); }
-
- AVLTree() { abs_.root = Null(); }
-
- class Iterator {
- public:
- // Initialize depth to invalid value, to indicate iterator is
- // invalid. (Depth is zero-base.)
- Iterator() { depth_ = ~0U; }
-
- void StartIter(AVLTree* tree, key k, SearchType st = EQUAL) {
- // Mask of high bit in an int.
- const int kMaskHighBit = static_cast<int>(~((~(unsigned)0) >> 1));
-
- // Save the tree that we're going to iterate through in a
- // member variable.
- tree_ = tree;
-
- int cmp, target_cmp;
- handle h = tree_->abs_.root;
- unsigned d = 0;
-
- depth_ = ~0U;
-
- if (h == Null()) {
- // Tree is empty.
- return;
- }
-
- if (st & LESS) {
- // Key can be greater than key of starting node.
- target_cmp = 1;
- } else if (st & GREATER) {
- // Key can be less than key of starting node.
- target_cmp = -1;
- } else {
- // Key must be same as key of starting node.
- target_cmp = 0;
- }
-
- for (;;) {
- cmp = CmpKN(k, h);
- if (cmp == 0) {
- if (st & EQUAL) {
- // Equal node was sought and found as starting node.
- depth_ = d;
- break;
- }
- cmp = -target_cmp;
- } else if (target_cmp != 0) {
- if (!((cmp ^ target_cmp) & kMaskHighBit)) {
- // cmp and target_cmp are both negative or both positive.
- depth_ = d;
- }
- }
- h = cmp < 0 ? GetLT(h) : GetGT(h);
- if (h == Null())
- break;
- branch_[d] = cmp > 0;
- path_h_[d++] = h;
- }
- }
-
- void StartIterLeast(AVLTree* tree) {
- tree_ = tree;
-
- handle h = tree_->abs_.root;
-
- depth_ = ~0U;
-
- branch_.Reset();
-
- while (h != Null()) {
- if (depth_ != ~0U)
- path_h_[depth_] = h;
- depth_++;
- h = GetLT(h);
- }
- }
-
- void StartIterGreatest(AVLTree* tree) {
- tree_ = tree;
-
- handle h = tree_->abs_.root;
-
- depth_ = ~0U;
-
- branch_.Set();
-
- while (h != Null()) {
- if (depth_ != ~0U)
- path_h_[depth_] = h;
- depth_++;
- h = GetGT(h);
- }
- }
-
- handle operator*() {
- if (depth_ == ~0U)
- return Null();
-
- return depth_ == 0 ? tree_->abs_.root : path_h_[depth_ - 1];
- }
-
- void operator++() {
- if (depth_ != ~0U) {
- handle h = GetGT(**this);
- if (h == Null()) {
- do {
- if (depth_ == 0) {
- depth_ = ~0U;
- break;
- }
- depth_--;
- } while (branch_[depth_]);
- } else {
- branch_[depth_] = true;
- path_h_[depth_++] = h;
- for (;;) {
- h = GetLT(h);
- if (h == Null())
- break;
- branch_[depth_] = false;
- path_h_[depth_++] = h;
- }
- }
- }
- }
-
- void operator--() {
- if (depth_ != ~0U) {
- handle h = GetLT(**this);
- if (h == Null()) {
- do {
- if (depth_ == 0) {
- depth_ = ~0U;
- break;
- }
- depth_--;
- } while (!branch_[depth_]);
- } else {
- branch_[depth_] = false;
- path_h_[depth_++] = h;
- for (;;) {
- h = GetGT(h);
- if (h == Null())
- break;
- branch_[depth_] = true;
- path_h_[depth_++] = h;
- }
- }
- }
- }
-
- void operator++(int /*ignored*/) { ++(*this); }
- void operator--(int /*ignored*/) { --(*this); }
-
- protected:
- // Tree being iterated over.
- AVLTree* tree_;
-
- // Records a path into the tree. If branch_[n] is true, indicates
- // take greater branch from the nth node in the path, otherwise
- // take the less branch. branch_[0] gives branch from root, and
- // so on.
- BSet branch_;
-
- // Zero-based depth of path into tree.
- unsigned depth_;
-
- // Handles of nodes in path from root to current node (returned by *).
- static const size_t kPathSize = maxDepth - 1;
- handle path_h_[kPathSize];
-
- int CmpKN(key k, handle h) { return tree_->abs_.CompareKeyNode(k, h); }
- int CmpNN(handle h1, handle h2) {
- return tree_->abs_.CompareNodeNode(h1, h2);
- }
- handle GetLT(handle h) { return tree_->abs_.GetLess(h); }
- handle GetGT(handle h) { return tree_->abs_.GetGreater(h); }
- handle Null() { return tree_->abs_.Null(); }
- };
-
- template <typename fwd_iter>
- bool Build(fwd_iter p, size num_nodes) {
- if (num_nodes == 0) {
- abs_.root = Null();
- return true;
- }
-
- // Gives path to subtree being built. If branch[N] is false, branch
- // less from the node at depth N, if true branch greater.
- BSet branch;
-
- // If rem[N] is true, then for the current subtree at depth N, it's
- // greater subtree has one more node than it's less subtree.
- BSet rem;
-
- // Depth of root node of current subtree.
- unsigned depth = 0;
-
- // Number of nodes in current subtree.
- size num_sub = num_nodes;
-
- // The algorithm relies on a stack of nodes whose less subtree has
- // been built, but whose right subtree has not yet been built. The
- // stack is implemented as linked list. The nodes are linked
- // together by having the "greater" handle of a node set to the
- // next node in the list. "less_parent" is the handle of the first
- // node in the list.
- handle less_parent = Null();
-
- // h is root of current subtree, child is one of its children.
- handle h, child;
-
- for (;;) {
- while (num_sub > 2) {
- // Subtract one for root of subtree.
- num_sub--;
- rem[depth] = !!(num_sub & 1);
- branch[depth++] = false;
- num_sub >>= 1;
- }
-
- if (num_sub == 2) {
- // Build a subtree with two nodes, slanting to greater.
- // I arbitrarily chose to always have the extra node in the
- // greater subtree when there is an odd number of nodes to
- // split between the two subtrees.
-
- h = *p;
- p++;
- child = *p;
- p++;
- SetLT(child, Null());
- SetGT(child, Null());
- SetBF(child, 0);
- SetGT(h, child);
- SetLT(h, Null());
- SetBF(h, 1);
- } else { // num_sub == 1
- // Build a subtree with one node.
-
- h = *p;
- p++;
- SetLT(h, Null());
- SetGT(h, Null());
- SetBF(h, 0);
- }
-
- while (depth) {
- depth--;
- if (!branch[depth]) {
- // We've completed a less subtree.
- break;
- }
-
- // We've completed a greater subtree, so attach it to
- // its parent (that is less than it). We pop the parent
- // off the stack of less parents.
- child = h;
- h = less_parent;
- less_parent = GetGT(h);
- SetGT(h, child);
- // num_sub = 2 * (num_sub - rem[depth]) + rem[depth] + 1
- num_sub <<= 1;
- num_sub += 1 - rem[depth];
- if (num_sub & (num_sub - 1)) {
- // num_sub is not a power of 2
- SetBF(h, 0);
- } else {
- // num_sub is a power of 2
- SetBF(h, 1);
- }
- }
-
- if (num_sub == num_nodes) {
- // We've completed the full tree.
- break;
- }
-
- // The subtree we've completed is the less subtree of the
- // next node in the sequence.
-
- child = h;
- h = *p;
- p++;
- SetLT(h, child);
-
- // Put h into stack of less parents.
- SetGT(h, less_parent);
- less_parent = h;
-
- // Proceed to creating greater than subtree of h.
- branch[depth] = true;
- num_sub += rem[depth++];
- } // end for (;;)
-
- abs_.root = h;
-
- return true;
- }
-
- protected:
- friend class Iterator;
-
- // Create a class whose sole purpose is to take advantage of
- // the "empty member" optimization.
- struct abs_plus_root : public Abstractor {
- // The handle of the root element in the AVL tree.
- handle root;
- };
-
- abs_plus_root abs_;
-
- handle GetLT(handle h) { return abs_.GetLess(h); }
- void SetLT(handle h, handle lh) { abs_.SetLess(h, lh); }
-
- handle GetGT(handle h) { return abs_.GetGreater(h); }
- void SetGT(handle h, handle gh) { abs_.SetGreater(h, gh); }
-
- int GetBF(handle h) { return abs_.GetBalanceFactor(h); }
- void SetBF(handle h, int bf) { abs_.SetBalanceFactor(h, bf); }
-
- int CmpKN(key k, handle h) { return abs_.CompareKeyNode(k, h); }
- int CmpNN(handle h1, handle h2) { return abs_.CompareNodeNode(h1, h2); }
-
- handle Null() { return abs_.Null(); }
-
- private:
- // Balances subtree, returns handle of root node of subtree
- // after balancing.
- handle Balance(handle bal_h) {
- handle deep_h;
-
- // Either the "greater than" or the "less than" subtree of
- // this node has to be 2 levels deeper (or else it wouldn't
- // need balancing).
-
- if (GetBF(bal_h) > 0) {
- // "Greater than" subtree is deeper.
-
- deep_h = GetGT(bal_h);
-
- if (GetBF(deep_h) < 0) {
- handle old_h = bal_h;
- bal_h = GetLT(deep_h);
-
- SetGT(old_h, GetLT(bal_h));
- SetLT(deep_h, GetGT(bal_h));
- SetLT(bal_h, old_h);
- SetGT(bal_h, deep_h);
-
- int bf = GetBF(bal_h);
- if (bf != 0) {
- if (bf > 0) {
- SetBF(old_h, -1);
- SetBF(deep_h, 0);
- } else {
- SetBF(deep_h, 1);
- SetBF(old_h, 0);
- }
- SetBF(bal_h, 0);
- } else {
- SetBF(old_h, 0);
- SetBF(deep_h, 0);
- }
- } else {
- SetGT(bal_h, GetLT(deep_h));
- SetLT(deep_h, bal_h);
- if (GetBF(deep_h) == 0) {
- SetBF(deep_h, -1);
- SetBF(bal_h, 1);
- } else {
- SetBF(deep_h, 0);
- SetBF(bal_h, 0);
- }
- bal_h = deep_h;
- }
- } else {
- // "Less than" subtree is deeper.
-
- deep_h = GetLT(bal_h);
-
- if (GetBF(deep_h) > 0) {
- handle old_h = bal_h;
- bal_h = GetGT(deep_h);
- SetLT(old_h, GetGT(bal_h));
- SetGT(deep_h, GetLT(bal_h));
- SetGT(bal_h, old_h);
- SetLT(bal_h, deep_h);
-
- int bf = GetBF(bal_h);
- if (bf != 0) {
- if (bf < 0) {
- SetBF(old_h, 1);
- SetBF(deep_h, 0);
- } else {
- SetBF(deep_h, -1);
- SetBF(old_h, 0);
- }
- SetBF(bal_h, 0);
- } else {
- SetBF(old_h, 0);
- SetBF(deep_h, 0);
- }
- } else {
- SetLT(bal_h, GetGT(deep_h));
- SetGT(deep_h, bal_h);
- if (GetBF(deep_h) == 0) {
- SetBF(deep_h, 1);
- SetBF(bal_h, -1);
- } else {
- SetBF(deep_h, 0);
- SetBF(bal_h, 0);
- }
- bal_h = deep_h;
- }
- }
-
- return bal_h;
- }
-};
-
-template <class Abstractor, unsigned maxDepth, class BSet>
-inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
-AVLTree<Abstractor, maxDepth, BSet>::Insert(handle h) {
- SetLT(h, Null());
- SetGT(h, Null());
- SetBF(h, 0);
-
- if (abs_.root == Null()) {
- abs_.root = h;
- } else {
- // Last unbalanced node encountered in search for insertion point.
- handle unbal = Null();
- // Parent of last unbalanced node.
- handle parent_unbal = Null();
- // Balance factor of last unbalanced node.
- int unbal_bf;
-
- // Zero-based depth in tree.
- unsigned depth = 0, unbal_depth = 0;
-
- // Records a path into the tree. If branch[n] is true, indicates
- // take greater branch from the nth node in the path, otherwise
- // take the less branch. branch[0] gives branch from root, and
- // so on.
- BSet branch;
-
- handle hh = abs_.root;
- handle parent = Null();
- int cmp;
-
- do {
- if (GetBF(hh) != 0) {
- unbal = hh;
- parent_unbal = parent;
- unbal_depth = depth;
- }
- cmp = CmpNN(h, hh);
- if (cmp == 0) {
- // Duplicate key.
- return hh;
- }
- parent = hh;
- hh = cmp < 0 ? GetLT(hh) : GetGT(hh);
- branch[depth++] = cmp > 0;
- } while (hh != Null());
-
- // Add node to insert as leaf of tree.
- if (cmp < 0)
- SetLT(parent, h);
- else
- SetGT(parent, h);
-
- depth = unbal_depth;
-
- if (unbal == Null()) {
- hh = abs_.root;
- } else {
- cmp = branch[depth++] ? 1 : -1;
- unbal_bf = GetBF(unbal);
- if (cmp < 0)
- unbal_bf--;
- else // cmp > 0
- unbal_bf++;
- hh = cmp < 0 ? GetLT(unbal) : GetGT(unbal);
- if ((unbal_bf != -2) && (unbal_bf != 2)) {
- // No rebalancing of tree is necessary.
- SetBF(unbal, unbal_bf);
- unbal = Null();
- }
- }
-
- if (hh != Null()) {
- while (h != hh) {
- cmp = branch[depth++] ? 1 : -1;
- if (cmp < 0) {
- SetBF(hh, -1);
- hh = GetLT(hh);
- } else { // cmp > 0
- SetBF(hh, 1);
- hh = GetGT(hh);
- }
- }
- }
-
- if (unbal != Null()) {
- unbal = Balance(unbal);
- if (parent_unbal == Null()) {
- abs_.root = unbal;
- } else {
- depth = unbal_depth - 1;
- cmp = branch[depth] ? 1 : -1;
- if (cmp < 0)
- SetLT(parent_unbal, unbal);
- else // cmp > 0
- SetGT(parent_unbal, unbal);
- }
- }
- }
-
- return h;
-}
-
-template <class Abstractor, unsigned maxDepth, class BSet>
-inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
-AVLTree<Abstractor, maxDepth, BSet>::Search(
- key k,
- typename AVLTree<Abstractor, maxDepth, BSet>::SearchType st) {
- const int kMaskHighBit = static_cast<int>(~((~(unsigned)0) >> 1));
-
- int cmp, target_cmp;
- handle match_h = Null();
- handle h = abs_.root;
-
- if (st & LESS)
- target_cmp = 1;
- else if (st & GREATER)
- target_cmp = -1;
- else
- target_cmp = 0;
-
- while (h != Null()) {
- cmp = CmpKN(k, h);
- if (cmp == 0) {
- if (st & EQUAL) {
- match_h = h;
- break;
- }
- cmp = -target_cmp;
- } else if (target_cmp != 0) {
- if (!((cmp ^ target_cmp) & kMaskHighBit)) {
- // cmp and target_cmp are both positive or both negative.
- match_h = h;
- }
- }
- h = cmp < 0 ? GetLT(h) : GetGT(h);
- }
-
- return match_h;
-}
-
-template <class Abstractor, unsigned maxDepth, class BSet>
-inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
-AVLTree<Abstractor, maxDepth, BSet>::SearchLeast() {
- handle h = abs_.root, parent = Null();
-
- while (h != Null()) {
- parent = h;
- h = GetLT(h);
- }
-
- return parent;
-}
-
-template <class Abstractor, unsigned maxDepth, class BSet>
-inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
-AVLTree<Abstractor, maxDepth, BSet>::SearchGreatest() {
- handle h = abs_.root, parent = Null();
-
- while (h != Null()) {
- parent = h;
- h = GetGT(h);
- }
-
- return parent;
-}
-
-template <class Abstractor, unsigned maxDepth, class BSet>
-inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
-AVLTree<Abstractor, maxDepth, BSet>::Remove(key k) {
- // Zero-based depth in tree.
- unsigned depth = 0, rm_depth;
-
- // Records a path into the tree. If branch[n] is true, indicates
- // take greater branch from the nth node in the path, otherwise
- // take the less branch. branch[0] gives branch from root, and
- // so on.
- BSet branch;
-
- handle h = abs_.root;
- handle parent = Null(), child;
- int cmp, cmp_shortened_sub_with_path = 0;
-
- for (;;) {
- if (h == Null()) {
- // No node in tree with given key.
- return Null();
- }
- cmp = CmpKN(k, h);
- if (cmp == 0) {
- // Found node to remove.
- break;
- }
- parent = h;
- h = cmp < 0 ? GetLT(h) : GetGT(h);
- branch[depth++] = cmp > 0;
- cmp_shortened_sub_with_path = cmp;
- }
- handle rm = h;
- handle parent_rm = parent;
- rm_depth = depth;
-
- // If the node to remove is not a leaf node, we need to get a
- // leaf node, or a node with a single leaf as its child, to put
- // in the place of the node to remove. We will get the greatest
- // node in the less subtree (of the node to remove), or the least
- // node in the greater subtree. We take the leaf node from the
- // deeper subtree, if there is one.
-
- if (GetBF(h) < 0) {
- child = GetLT(h);
- branch[depth] = false;
- cmp = -1;
- } else {
- child = GetGT(h);
- branch[depth] = true;
- cmp = 1;
- }
- depth++;
-
- if (child != Null()) {
- cmp = -cmp;
- do {
- parent = h;
- h = child;
- if (cmp < 0) {
- child = GetLT(h);
- branch[depth] = false;
- } else {
- child = GetGT(h);
- branch[depth] = true;
- }
- depth++;
- } while (child != Null());
-
- if (parent == rm) {
- // Only went through do loop once. Deleted node will be replaced
- // in the tree structure by one of its immediate children.
- cmp_shortened_sub_with_path = -cmp;
- } else {
- cmp_shortened_sub_with_path = cmp;
- }
-
- // Get the handle of the opposite child, which may not be null.
- child = cmp > 0 ? GetLT(h) : GetGT(h);
- }
-
- if (parent == Null()) {
- // There were only 1 or 2 nodes in this tree.
- abs_.root = child;
- } else if (cmp_shortened_sub_with_path < 0) {
- SetLT(parent, child);
- } else {
- SetGT(parent, child);
- }
-
- // "path" is the parent of the subtree being eliminated or reduced
- // from a depth of 2 to 1. If "path" is the node to be removed, we
- // set path to the node we're about to poke into the position of the
- // node to be removed.
- handle path = parent == rm ? h : parent;
-
- if (h != rm) {
- // Poke in the replacement for the node to be removed.
- SetLT(h, GetLT(rm));
- SetGT(h, GetGT(rm));
- SetBF(h, GetBF(rm));
- if (parent_rm == Null()) {
- abs_.root = h;
- } else {
- depth = rm_depth - 1;
- if (branch[depth])
- SetGT(parent_rm, h);
- else
- SetLT(parent_rm, h);
- }
- }
-
- if (path != Null()) {
- // Create a temporary linked list from the parent of the path node
- // to the root node.
- h = abs_.root;
- parent = Null();
- depth = 0;
- while (h != path) {
- if (branch[depth++]) {
- child = GetGT(h);
- SetGT(h, parent);
- } else {
- child = GetLT(h);
- SetLT(h, parent);
- }
- parent = h;
- h = child;
- }
-
- // Climb from the path node to the root node using the linked
- // list, restoring the tree structure and rebalancing as necessary.
- bool reduced_depth = true;
- int bf;
- cmp = cmp_shortened_sub_with_path;
- for (;;) {
- if (reduced_depth) {
- bf = GetBF(h);
- if (cmp < 0)
- bf++;
- else // cmp > 0
- bf--;
- if ((bf == -2) || (bf == 2)) {
- h = Balance(h);
- bf = GetBF(h);
- } else {
- SetBF(h, bf);
- }
- reduced_depth = (bf == 0);
- }
- if (parent == Null())
- break;
- child = h;
- h = parent;
- cmp = branch[--depth] ? 1 : -1;
- if (cmp < 0) {
- parent = GetLT(h);
- SetLT(h, child);
- } else {
- parent = GetGT(h);
- SetGT(h, child);
- }
- }
- abs_.root = h;
- }
-
- return rm;
-}
-
-template <class Abstractor, unsigned maxDepth, class BSet>
-inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
-AVLTree<Abstractor, maxDepth, BSet>::Subst(handle new_node) {
- handle h = abs_.root;
- handle parent = Null();
- int cmp, last_cmp;
-
- // Search for node already in tree with same key.
- for (;;) {
- if (h == Null()) {
- // No node in tree with same key as new node.
- return Null();
- }
- cmp = CmpNN(new_node, h);
- if (cmp == 0) {
- // Found the node to substitute new one for.
- break;
- }
- last_cmp = cmp;
- parent = h;
- h = cmp < 0 ? GetLT(h) : GetGT(h);
- }
-
- // Copy tree housekeeping fields from node in tree to new node.
- SetLT(new_node, GetLT(h));
- SetGT(new_node, GetGT(h));
- SetBF(new_node, GetBF(h));
-
- if (parent == Null()) {
- // New node is also new root.
- abs_.root = new_node;
- } else {
- // Make parent point to new node.
- if (last_cmp < 0)
- SetLT(parent, new_node);
- else
- SetGT(parent, new_node);
- }
-
- return h;
-}
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_INDEXED_DB_LEVELDB_AVLTREE_H_
diff --git a/chromium/content/browser/indexed_db/leveldb/fixed_array.h b/chromium/content/browser/indexed_db/leveldb/fixed_array.h
deleted file mode 100644
index cef43973fb0..00000000000
--- a/chromium/content/browser/indexed_db/leveldb/fixed_array.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.
-
-/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef CONTENT_BROWSER_INDEXED_DB_LEVELDB_FIXED_ARRAY_H_
-#define CONTENT_BROWSER_INDEXED_DB_LEVELDB_FIXED_ARRAY_H_
-
-#include "base/logging.h"
-
-namespace content {
-
-template <typename T, size_t Size>
-class FixedArray {
- public:
- T& operator[](size_t i) {
-#if defined(ADDRESS_SANITIZER)
- CHECK(i < Size);
-#endif
- return data_[i];
- }
-
- const T& operator[](size_t i) const {
-#if defined(ADDRESS_SANITIZER)
- CHECK(i < Size);
-#endif
- return data_[i];
- }
-
- T* data() { return data_; }
- size_t size() const { return Size; }
-
- private:
- T data_[Size];
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_INDEXED_DB_LEVELDB_FIXED_ARRAY_H_
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc b/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc
index 03d8ca6ccf0..cab8473a7a3 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc
@@ -121,9 +121,9 @@ static int CheckFreeSpace(const char* const type,
base::HistogramBase::kUmaTargetedHistogramFlag)->Add(1 /*sample*/);
return -1;
}
- int clamped_disk_space_k_bytes =
- free_disk_space_in_k_bytes > INT_MAX ? INT_MAX
- : free_disk_space_in_k_bytes;
+ int clamped_disk_space_k_bytes = free_disk_space_in_k_bytes > INT_MAX
+ ? INT_MAX
+ : free_disk_space_in_k_bytes;
const uint64 histogram_max = static_cast<uint64>(1e9);
COMPILE_ASSERT(histogram_max <= INT_MAX, histogram_max_too_big);
base::Histogram::FactoryGet(name,
@@ -268,11 +268,10 @@ static void HistogramLevelDBError(const std::string& histogram_name,
ParseAndHistogramCorruptionDetails(histogram_name, s);
}
-leveldb::Status LevelDBDatabase::Open(
- const base::FilePath& file_name,
- const LevelDBComparator* comparator,
- scoped_ptr<LevelDBDatabase>* result,
- bool* is_disk_full) {
+leveldb::Status LevelDBDatabase::Open(const base::FilePath& file_name,
+ const LevelDBComparator* comparator,
+ scoped_ptr<LevelDBDatabase>* result,
+ bool* is_disk_full) {
scoped_ptr<ComparatorAdapter> comparator_adapter(
new ComparatorAdapter(comparator));
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_database.h b/chromium/content/browser/indexed_db/leveldb/leveldb_database.h
index 1efeefa2d17..5732ac4e3d6 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_database.h
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_database.h
@@ -6,7 +6,6 @@
#define CONTENT_BROWSER_INDEXED_DB_LEVELDB_LEVELDB_DATABASE_H_
#include <string>
-#include <vector>
#include "base/files/file_path.h"
#include "base/memory/scoped_ptr.h"
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_transaction.cc b/chromium/content/browser/indexed_db/leveldb/leveldb_transaction.cc
index 5388d44c6f5..0c3619465bb 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_transaction.cc
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_transaction.cc
@@ -14,49 +14,43 @@ using base::StringPiece;
namespace content {
LevelDBTransaction::LevelDBTransaction(LevelDBDatabase* db)
- : db_(db), snapshot_(db), comparator_(db->Comparator()), finished_(false) {
- tree_.abstractor().comparator_ = comparator_;
-}
-
-LevelDBTransaction::AVLTreeNode::AVLTreeNode() {}
-LevelDBTransaction::AVLTreeNode::~AVLTreeNode() {}
-
-void LevelDBTransaction::ClearTree() {
- TreeType::Iterator iterator;
- iterator.StartIterLeast(&tree_);
-
- std::vector<AVLTreeNode*> nodes;
-
- while (*iterator) {
- nodes.push_back(*iterator);
- ++iterator;
+ : db_(db),
+ snapshot_(db),
+ comparator_(db->Comparator()),
+ data_comparator_(comparator_),
+ data_(data_comparator_),
+ finished_(false) {}
+
+LevelDBTransaction::Record::Record() : deleted(false) {}
+LevelDBTransaction::Record::~Record() {}
+
+void LevelDBTransaction::Clear() {
+ for (DataType::iterator it = data_.begin(); it != data_.end(); ++it) {
+ delete it->second;
}
- tree_.Purge();
-
- for (size_t i = 0; i < nodes.size(); ++i)
- delete nodes[i];
+ data_.clear();
}
-LevelDBTransaction::~LevelDBTransaction() { ClearTree(); }
+LevelDBTransaction::~LevelDBTransaction() { Clear(); }
void LevelDBTransaction::Set(const StringPiece& key,
std::string* value,
bool deleted) {
DCHECK(!finished_);
- bool new_node = false;
- AVLTreeNode* node = tree_.Search(key);
-
- if (!node) {
- node = new AVLTreeNode;
- node->key = key.as_string();
- tree_.Insert(node);
- new_node = true;
+ DataType::iterator it = data_.find(key);
+
+ if (it == data_.end()) {
+ Record* record = new Record();
+ record->key.assign(key.begin(), key.end() - key.begin());
+ record->value.swap(*value);
+ record->deleted = deleted;
+ data_[record->key] = record;
+ NotifyIterators();
+ return;
}
- node->value.swap(*value);
- node->deleted = deleted;
- if (new_node)
- NotifyIteratorsOfTreeChange();
+ it->second->value.swap(*value);
+ it->second->deleted = deleted;
}
void LevelDBTransaction::Put(const StringPiece& key, std::string* value) {
@@ -73,13 +67,14 @@ bool LevelDBTransaction::Get(const StringPiece& key,
bool* found) {
*found = false;
DCHECK(!finished_);
- AVLTreeNode* node = tree_.Search(key);
+ std::string string_key(key.begin(), key.end() - key.begin());
+ DataType::const_iterator it = data_.find(string_key);
- if (node) {
- if (node->deleted)
+ if (it != data_.end()) {
+ if (it->second->deleted)
return true;
- *value = node->value;
+ *value = it->second->value;
*found = true;
return true;
}
@@ -95,29 +90,25 @@ bool LevelDBTransaction::Get(const StringPiece& key,
bool LevelDBTransaction::Commit() {
DCHECK(!finished_);
- if (tree_.IsEmpty()) {
+ if (data_.empty()) {
finished_ = true;
return true;
}
scoped_ptr<LevelDBWriteBatch> write_batch = LevelDBWriteBatch::Create();
- TreeType::Iterator iterator;
- iterator.StartIterLeast(&tree_);
-
- while (*iterator) {
- AVLTreeNode* node = *iterator;
- if (!node->deleted)
- write_batch->Put(node->key, node->value);
+ for (DataType::iterator iterator = data_.begin(); iterator != data_.end();
+ ++iterator) {
+ if (!iterator->second->deleted)
+ write_batch->Put(iterator->first, iterator->second->value);
else
- write_batch->Remove(node->key);
- ++iterator;
+ write_batch->Remove(iterator->first);
}
if (!db_->Write(*write_batch))
return false;
- ClearTree();
+ Clear();
finished_ = true;
return true;
}
@@ -125,80 +116,66 @@ bool LevelDBTransaction::Commit() {
void LevelDBTransaction::Rollback() {
DCHECK(!finished_);
finished_ = true;
- ClearTree();
+ Clear();
}
scoped_ptr<LevelDBIterator> LevelDBTransaction::CreateIterator() {
return TransactionIterator::Create(this).PassAs<LevelDBIterator>();
}
-scoped_ptr<LevelDBTransaction::TreeIterator>
-LevelDBTransaction::TreeIterator::Create(LevelDBTransaction* transaction) {
- return make_scoped_ptr(new TreeIterator(transaction));
+scoped_ptr<LevelDBTransaction::DataIterator>
+LevelDBTransaction::DataIterator::Create(LevelDBTransaction* transaction) {
+ return make_scoped_ptr(new DataIterator(transaction));
}
-bool LevelDBTransaction::TreeIterator::IsValid() const { return !!*iterator_; }
-
-void LevelDBTransaction::TreeIterator::SeekToLast() {
- iterator_.StartIterGreatest(tree_);
- if (IsValid())
- key_ = (*iterator_)->key;
+bool LevelDBTransaction::DataIterator::IsValid() const {
+ return iterator_ != data_->end();
}
-void LevelDBTransaction::TreeIterator::Seek(const StringPiece& target) {
- iterator_.StartIter(tree_, target, TreeType::EQUAL);
- if (!IsValid())
- iterator_.StartIter(tree_, target, TreeType::GREATER);
+void LevelDBTransaction::DataIterator::SeekToLast() {
+ iterator_ = data_->end();
+ if (iterator_ != data_->begin())
+ --iterator_;
+}
- if (IsValid())
- key_ = (*iterator_)->key;
+void LevelDBTransaction::DataIterator::Seek(const StringPiece& target) {
+ iterator_ = data_->lower_bound(target);
}
-void LevelDBTransaction::TreeIterator::Next() {
+void LevelDBTransaction::DataIterator::Next() {
DCHECK(IsValid());
++iterator_;
- if (IsValid()) {
- DCHECK_GE(transaction_->comparator_->Compare((*iterator_)->key, key_), 0);
- key_ = (*iterator_)->key;
- }
}
-void LevelDBTransaction::TreeIterator::Prev() {
+void LevelDBTransaction::DataIterator::Prev() {
DCHECK(IsValid());
- --iterator_;
- if (IsValid()) {
- DCHECK_LT(tree_->abstractor().comparator_->Compare((*iterator_)->key, key_),
- 0);
- key_ = (*iterator_)->key;
- }
+ if (iterator_ != data_->begin())
+ --iterator_;
+ else
+ iterator_ = data_->end();
}
-StringPiece LevelDBTransaction::TreeIterator::Key() const {
+StringPiece LevelDBTransaction::DataIterator::Key() const {
DCHECK(IsValid());
- return key_;
+ return iterator_->first;
}
-StringPiece LevelDBTransaction::TreeIterator::Value() const {
+StringPiece LevelDBTransaction::DataIterator::Value() const {
DCHECK(IsValid());
DCHECK(!IsDeleted());
- return (*iterator_)->value;
+ return iterator_->second->value;
}
-bool LevelDBTransaction::TreeIterator::IsDeleted() const {
+bool LevelDBTransaction::DataIterator::IsDeleted() const {
DCHECK(IsValid());
- return (*iterator_)->deleted;
+ return iterator_->second->deleted;
}
-void LevelDBTransaction::TreeIterator::Reset() {
- DCHECK(IsValid());
- iterator_.StartIter(tree_, key_, TreeType::EQUAL);
- DCHECK(IsValid());
-}
+LevelDBTransaction::DataIterator::~DataIterator() {}
-LevelDBTransaction::TreeIterator::~TreeIterator() {}
-
-LevelDBTransaction::TreeIterator::TreeIterator(LevelDBTransaction* transaction)
- : tree_(&transaction->tree_), transaction_(transaction) {}
+LevelDBTransaction::DataIterator::DataIterator(LevelDBTransaction* transaction)
+ : data_(&transaction->data_),
+ iterator_(data_->end()) {}
scoped_ptr<LevelDBTransaction::TransactionIterator>
LevelDBTransaction::TransactionIterator::Create(
@@ -210,11 +187,11 @@ LevelDBTransaction::TransactionIterator::TransactionIterator(
scoped_refptr<LevelDBTransaction> transaction)
: transaction_(transaction),
comparator_(transaction_->comparator_),
- tree_iterator_(TreeIterator::Create(transaction_.get())),
+ data_iterator_(DataIterator::Create(transaction_.get())),
db_iterator_(transaction_->db_->CreateIterator(&transaction_->snapshot_)),
current_(0),
direction_(FORWARD),
- tree_changed_(false) {
+ data_changed_(false) {
transaction_->RegisterIterator(this);
}
@@ -227,7 +204,7 @@ bool LevelDBTransaction::TransactionIterator::IsValid() const {
}
void LevelDBTransaction::TransactionIterator::SeekToLast() {
- tree_iterator_->SeekToLast();
+ data_iterator_->SeekToLast();
db_iterator_->SeekToLast();
direction_ = REVERSE;
@@ -236,7 +213,7 @@ void LevelDBTransaction::TransactionIterator::SeekToLast() {
}
void LevelDBTransaction::TransactionIterator::Seek(const StringPiece& target) {
- tree_iterator_->Seek(target);
+ data_iterator_->Seek(target);
db_iterator_->Seek(target);
direction_ = FORWARD;
@@ -246,22 +223,23 @@ void LevelDBTransaction::TransactionIterator::Seek(const StringPiece& target) {
void LevelDBTransaction::TransactionIterator::Next() {
DCHECK(IsValid());
- if (tree_changed_)
- RefreshTreeIterator();
+ if (data_changed_)
+ RefreshDataIterator();
if (direction_ != FORWARD) {
// Ensure the non-current iterator is positioned after Key().
LevelDBIterator* non_current = (current_ == db_iterator_.get())
- ? tree_iterator_.get()
+ ? data_iterator_.get()
: db_iterator_.get();
non_current->Seek(Key());
if (non_current->IsValid() &&
- !comparator_->Compare(non_current->Key(), Key()))
- non_current->Next(); // Take an extra step so the non-current key is
- // strictly greater than Key().
-
+ !comparator_->Compare(non_current->Key(), Key())) {
+ // Take an extra step so the non-current key is
+ // strictly greater than Key().
+ non_current->Next();
+ }
DCHECK(!non_current->IsValid() ||
comparator_->Compare(non_current->Key(), Key()) > 0);
@@ -275,14 +253,14 @@ void LevelDBTransaction::TransactionIterator::Next() {
void LevelDBTransaction::TransactionIterator::Prev() {
DCHECK(IsValid());
- if (tree_changed_)
- RefreshTreeIterator();
+ if (data_changed_)
+ RefreshDataIterator();
if (direction_ != REVERSE) {
// Ensure the non-current iterator is positioned before Key().
LevelDBIterator* non_current = (current_ == db_iterator_.get())
- ? tree_iterator_.get()
+ ? data_iterator_.get()
: db_iterator_.get();
non_current->Seek(Key());
@@ -293,8 +271,8 @@ void LevelDBTransaction::TransactionIterator::Prev() {
// stepping, like we do in Next() above.
non_current->Prev();
} else {
- non_current->SeekToLast(); // Iterator has no entries >= Key(). Position
- // at last entry.
+ // Iterator has no entries >= Key(). Position at last entry.
+ non_current->SeekToLast();
}
DCHECK(!non_current->IsValid() ||
comparator_->Compare(non_current->Key(), Key()) < 0);
@@ -309,58 +287,58 @@ void LevelDBTransaction::TransactionIterator::Prev() {
StringPiece LevelDBTransaction::TransactionIterator::Key() const {
DCHECK(IsValid());
- if (tree_changed_)
- RefreshTreeIterator();
+ if (data_changed_)
+ RefreshDataIterator();
return current_->Key();
}
StringPiece LevelDBTransaction::TransactionIterator::Value() const {
DCHECK(IsValid());
- if (tree_changed_)
- RefreshTreeIterator();
+ if (data_changed_)
+ RefreshDataIterator();
return current_->Value();
}
-void LevelDBTransaction::TransactionIterator::TreeChanged() {
- tree_changed_ = true;
+void LevelDBTransaction::TransactionIterator::DataChanged() {
+ data_changed_ = true;
}
-void LevelDBTransaction::TransactionIterator::RefreshTreeIterator() const {
- DCHECK(tree_changed_);
+void LevelDBTransaction::TransactionIterator::RefreshDataIterator() const {
+ DCHECK(data_changed_);
- tree_changed_ = false;
+ data_changed_ = false;
- if (tree_iterator_->IsValid() && tree_iterator_.get() == current_) {
- tree_iterator_->Reset();
+ if (data_iterator_->IsValid() && data_iterator_.get() == current_) {
return;
}
if (db_iterator_->IsValid()) {
- // There could be new nodes in the tree that we should iterate over.
+ // There could be new records in data that we should iterate over.
if (direction_ == FORWARD) {
- // Try to seek tree iterator to something greater than the db iterator.
- tree_iterator_->Seek(db_iterator_->Key());
- if (tree_iterator_->IsValid() &&
- !comparator_->Compare(tree_iterator_->Key(), db_iterator_->Key()))
- tree_iterator_->Next(); // If equal, take another step so the tree
- // iterator is strictly greater.
+ // Try to seek data iterator to something greater than the db iterator.
+ data_iterator_->Seek(db_iterator_->Key());
+ if (data_iterator_->IsValid() &&
+ !comparator_->Compare(data_iterator_->Key(), db_iterator_->Key())) {
+ // If equal, take another step so the data iterator is strictly greater.
+ data_iterator_->Next();
+ }
} else {
// If going backward, seek to a key less than the db iterator.
DCHECK_EQ(REVERSE, direction_);
- tree_iterator_->Seek(db_iterator_->Key());
- if (tree_iterator_->IsValid())
- tree_iterator_->Prev();
+ data_iterator_->Seek(db_iterator_->Key());
+ if (data_iterator_->IsValid())
+ data_iterator_->Prev();
}
}
}
-bool LevelDBTransaction::TransactionIterator::TreeIteratorIsLower() const {
- return comparator_->Compare(tree_iterator_->Key(), db_iterator_->Key()) < 0;
+bool LevelDBTransaction::TransactionIterator::DataIteratorIsLower() const {
+ return comparator_->Compare(data_iterator_->Key(), db_iterator_->Key()) < 0;
}
-bool LevelDBTransaction::TransactionIterator::TreeIteratorIsHigher() const {
- return comparator_->Compare(tree_iterator_->Key(), db_iterator_->Key()) > 0;
+bool LevelDBTransaction::TransactionIterator::DataIteratorIsHigher() const {
+ return comparator_->Compare(data_iterator_->Key(), db_iterator_->Key()) > 0;
}
void LevelDBTransaction::TransactionIterator::HandleConflictsAndDeletes() {
@@ -369,9 +347,9 @@ void LevelDBTransaction::TransactionIterator::HandleConflictsAndDeletes() {
while (loop) {
loop = false;
- if (tree_iterator_->IsValid() && db_iterator_->IsValid() &&
- !comparator_->Compare(tree_iterator_->Key(), db_iterator_->Key())) {
- // For equal keys, the tree iterator takes precedence, so move the
+ if (data_iterator_->IsValid() && db_iterator_->IsValid() &&
+ !comparator_->Compare(data_iterator_->Key(), db_iterator_->Key())) {
+ // For equal keys, the data iterator takes precedence, so move the
// database iterator another step.
if (direction_ == FORWARD)
db_iterator_->Next();
@@ -379,16 +357,16 @@ void LevelDBTransaction::TransactionIterator::HandleConflictsAndDeletes() {
db_iterator_->Prev();
}
- // Skip over delete markers in the tree iterator until it catches up with
+ // Skip over delete markers in the data iterator until it catches up with
// the db iterator.
- if (tree_iterator_->IsValid() && tree_iterator_->IsDeleted()) {
+ if (data_iterator_->IsValid() && data_iterator_->IsDeleted()) {
if (direction_ == FORWARD &&
- (!db_iterator_->IsValid() || TreeIteratorIsLower())) {
- tree_iterator_->Next();
+ (!db_iterator_->IsValid() || DataIteratorIsLower())) {
+ data_iterator_->Next();
loop = true;
} else if (direction_ == REVERSE &&
- (!db_iterator_->IsValid() || TreeIteratorIsHigher())) {
- tree_iterator_->Prev();
+ (!db_iterator_->IsValid() || DataIteratorIsHigher())) {
+ data_iterator_->Prev();
loop = true;
}
}
@@ -399,8 +377,8 @@ void
LevelDBTransaction::TransactionIterator::SetCurrentIteratorToSmallestKey() {
LevelDBIterator* smallest = 0;
- if (tree_iterator_->IsValid())
- smallest = tree_iterator_.get();
+ if (data_iterator_->IsValid())
+ smallest = data_iterator_.get();
if (db_iterator_->IsValid()) {
if (!smallest ||
@@ -414,8 +392,8 @@ LevelDBTransaction::TransactionIterator::SetCurrentIteratorToSmallestKey() {
void LevelDBTransaction::TransactionIterator::SetCurrentIteratorToLargestKey() {
LevelDBIterator* largest = 0;
- if (tree_iterator_->IsValid())
- largest = tree_iterator_.get();
+ if (data_iterator_->IsValid())
+ largest = data_iterator_.get();
if (db_iterator_->IsValid()) {
if (!largest ||
@@ -436,12 +414,12 @@ void LevelDBTransaction::UnregisterIterator(TransactionIterator* iterator) {
iterators_.erase(iterator);
}
-void LevelDBTransaction::NotifyIteratorsOfTreeChange() {
+void LevelDBTransaction::NotifyIterators() {
for (std::set<TransactionIterator*>::iterator i = iterators_.begin();
i != iterators_.end();
++i) {
TransactionIterator* transaction_iterator = *i;
- transaction_iterator->TreeChanged();
+ transaction_iterator->DataChanged();
}
}
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_transaction.h b/chromium/content/browser/indexed_db/leveldb/leveldb_transaction.h
index 83b4763edc1..b7b5d64df1e 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_transaction.h
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_transaction.h
@@ -5,14 +5,13 @@
#ifndef CONTENT_BROWSER_INDEXED_DB_LEVELDB_LEVELDB_TRANSACTION_H_
#define CONTENT_BROWSER_INDEXED_DB_LEVELDB_LEVELDB_TRANSACTION_H_
+#include <map>
#include <set>
#include <string>
-#include <vector>
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_piece.h"
-#include "content/browser/indexed_db/leveldb/avltree.h"
#include "content/browser/indexed_db/leveldb/leveldb_comparator.h"
#include "content/browser/indexed_db/leveldb/leveldb_database.h"
#include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
@@ -38,53 +37,33 @@ class CONTENT_EXPORT LevelDBTransaction
virtual ~LevelDBTransaction();
friend class base::RefCounted<LevelDBTransaction>;
- struct AVLTreeNode {
- AVLTreeNode();
- ~AVLTreeNode();
+ struct Record {
+ Record();
+ ~Record();
std::string key;
std::string value;
bool deleted;
-
- AVLTreeNode* less;
- AVLTreeNode* greater;
- int balance_factor;
- DISALLOW_COPY_AND_ASSIGN(AVLTreeNode);
};
- struct AVLTreeAbstractor {
- typedef AVLTreeNode* handle;
- typedef size_t size;
- typedef base::StringPiece key;
-
- handle GetLess(handle h) { return h->less; }
- void SetLess(handle h, handle less) { h->less = less; }
- handle GetGreater(handle h) { return h->greater; }
- void SetGreater(handle h, handle greater) { h->greater = greater; }
-
- int GetBalanceFactor(handle h) { return h->balance_factor; }
- void SetBalanceFactor(handle h, int bf) { h->balance_factor = bf; }
-
- int CompareKeyKey(const key& ka, const key& kb) {
- return comparator_->Compare(ka, kb);
- }
- int CompareKeyNode(const key& k, handle h) {
- return CompareKeyKey(k, h->key);
- }
- int CompareNodeNode(handle ha, handle hb) {
- return CompareKeyKey(ha->key, hb->key);
+ class Comparator {
+ public:
+ explicit Comparator(const LevelDBComparator* comparator)
+ : comparator_(comparator) {}
+ bool operator()(const base::StringPiece& a,
+ const base::StringPiece& b) const {
+ return comparator_->Compare(a, b) < 0;
}
- static handle Null() { return 0; }
-
+ private:
const LevelDBComparator* comparator_;
};
- typedef AVLTree<AVLTreeAbstractor> TreeType;
+ typedef std::map<base::StringPiece, Record*, Comparator> DataType;
- class TreeIterator : public LevelDBIterator {
+ class DataIterator : public LevelDBIterator {
public:
- static scoped_ptr<TreeIterator> Create(LevelDBTransaction* transaction);
- virtual ~TreeIterator();
+ static scoped_ptr<DataIterator> Create(LevelDBTransaction* transaction);
+ virtual ~DataIterator();
virtual bool IsValid() const OVERRIDE;
virtual void SeekToLast() OVERRIDE;
@@ -94,14 +73,11 @@ class CONTENT_EXPORT LevelDBTransaction
virtual base::StringPiece Key() const OVERRIDE;
virtual base::StringPiece Value() const OVERRIDE;
bool IsDeleted() const;
- void Reset();
private:
- explicit TreeIterator(LevelDBTransaction* transaction);
- mutable TreeType::Iterator iterator_; // Dereferencing this is non-const.
- TreeType* tree_;
- LevelDBTransaction* transaction_;
- std::string key_;
+ explicit DataIterator(LevelDBTransaction* transaction);
+ DataType* data_;
+ DataType::iterator iterator_;
};
class TransactionIterator : public LevelDBIterator {
@@ -117,20 +93,20 @@ class CONTENT_EXPORT LevelDBTransaction
virtual void Prev() OVERRIDE;
virtual base::StringPiece Key() const OVERRIDE;
virtual base::StringPiece Value() const OVERRIDE;
- void TreeChanged();
+ void DataChanged();
private:
explicit TransactionIterator(scoped_refptr<LevelDBTransaction> transaction);
void HandleConflictsAndDeletes();
void SetCurrentIteratorToSmallestKey();
void SetCurrentIteratorToLargestKey();
- void RefreshTreeIterator() const;
- bool TreeIteratorIsLower() const;
- bool TreeIteratorIsHigher() const;
+ void RefreshDataIterator() const;
+ bool DataIteratorIsLower() const;
+ bool DataIteratorIsHigher() const;
scoped_refptr<LevelDBTransaction> transaction_;
const LevelDBComparator* comparator_;
- mutable scoped_ptr<TreeIterator> tree_iterator_;
+ mutable scoped_ptr<DataIterator> data_iterator_;
scoped_ptr<LevelDBIterator> db_iterator_;
LevelDBIterator* current_;
@@ -139,19 +115,20 @@ class CONTENT_EXPORT LevelDBTransaction
REVERSE
};
Direction direction_;
- mutable bool tree_changed_;
+ mutable bool data_changed_;
};
void Set(const base::StringPiece& key, std::string* value, bool deleted);
- void ClearTree();
+ void Clear();
void RegisterIterator(TransactionIterator* iterator);
void UnregisterIterator(TransactionIterator* iterator);
- void NotifyIteratorsOfTreeChange();
+ void NotifyIterators();
LevelDBDatabase* db_;
const LevelDBSnapshot snapshot_;
const LevelDBComparator* comparator_;
- TreeType tree_;
+ Comparator data_comparator_;
+ DataType data_;
bool finished_;
std::set<TransactionIterator*> iterators_;
};
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_unittest.cc b/chromium/content/browser/indexed_db/leveldb/leveldb_unittest.cc
index 9ce06641c61..de506c57597 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_unittest.cc
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_unittest.cc
@@ -197,6 +197,52 @@ TEST(LevelDBDatabaseTest, TransactionIterator) {
EXPECT_FALSE(it->IsValid());
}
+TEST(LevelDBDatabaseTest, TransactionCommitTest) {
+ base::ScopedTempDir temp_directory;
+ ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
+
+ const std::string key1("key1");
+ const std::string key2("key2");
+ const std::string value1("value1");
+ const std::string value2("value2");
+ const std::string value3("value3");
+
+ std::string put_value;
+ std::string got_value;
+ SimpleComparator comparator;
+ bool success;
+ bool found;
+
+ scoped_ptr<LevelDBDatabase> leveldb;
+ LevelDBDatabase::Open(temp_directory.path(), &comparator, &leveldb);
+ EXPECT_TRUE(leveldb);
+
+ scoped_refptr<LevelDBTransaction> transaction =
+ new LevelDBTransaction(leveldb.get());
+
+ put_value = value1;
+ transaction->Put(key1, &put_value);
+
+ put_value = value2;
+ transaction->Put(key2, &put_value);
+
+ put_value = value3;
+ transaction->Put(key2, &put_value);
+
+ success = transaction->Commit();
+ EXPECT_TRUE(success);
+
+ success = leveldb->Get(key1, &got_value, &found);
+ EXPECT_TRUE(success);
+ EXPECT_TRUE(found);
+ EXPECT_EQ(value1, got_value);
+
+ success = leveldb->Get(key2, &got_value, &found);
+ EXPECT_TRUE(success);
+ EXPECT_TRUE(found);
+ EXPECT_EQ(value3, got_value);
+}
+
} // namespace
} // namespace content
diff --git a/chromium/content/browser/indexed_db/list_set.h b/chromium/content/browser/indexed_db/list_set.h
index 1884b4bb925..e7945cae939 100644
--- a/chromium/content/browser/indexed_db/list_set.h
+++ b/chromium/content/browser/indexed_db/list_set.h
@@ -47,7 +47,7 @@ class list_set {
list_.erase(it);
}
- bool has(const T& elem) { return set_.find(elem) != set_.end(); }
+ bool has(const T& elem) const { return set_.find(elem) != set_.end(); }
size_t size() const {
DCHECK_EQ(list_.size(), set_.size());
diff --git a/chromium/content/browser/loader/async_resource_handler.cc b/chromium/content/browser/loader/async_resource_handler.cc
index 02e5552b901..c7d7f49db93 100644
--- a/chromium/content/browser/loader/async_resource_handler.cc
+++ b/chromium/content/browser/loader/async_resource_handler.cc
@@ -78,12 +78,12 @@ class DependentIOBuffer : public net::WrappedIOBuffer {
AsyncResourceHandler::AsyncResourceHandler(
ResourceMessageFilter* filter,
- int routing_id,
+ ResourceContext* resource_context,
net::URLRequest* request,
ResourceDispatcherHostImpl* rdh)
: ResourceMessageDelegate(request),
filter_(filter),
- routing_id_(routing_id),
+ resource_context_(resource_context),
request_(request),
rdh_(rdh),
pending_data_count_(0),
@@ -139,8 +139,8 @@ void AsyncResourceHandler::OnDataReceivedACK(int request_id) {
bool AsyncResourceHandler::OnUploadProgress(int request_id,
uint64 position,
uint64 size) {
- return filter_->Send(new ResourceMsg_UploadProgress(routing_id_, request_id,
- position, size));
+ return filter_->Send(new ResourceMsg_UploadProgress(request_id, position,
+ size));
}
bool AsyncResourceHandler::OnRequestRedirected(int request_id,
@@ -150,16 +150,15 @@ bool AsyncResourceHandler::OnRequestRedirected(int request_id,
*defer = did_defer_ = true;
if (rdh_->delegate()) {
- rdh_->delegate()->OnRequestRedirected(new_url, request_,
- filter_->resource_context(),
- response);
+ rdh_->delegate()->OnRequestRedirected(
+ new_url, request_, resource_context_, response);
}
DevToolsNetLogObserver::PopulateResponseInfo(request_, response);
response->head.request_start = request_->creation_time();
response->head.response_start = TimeTicks::Now();
return filter_->Send(new ResourceMsg_ReceivedRedirect(
- routing_id_, request_id, new_url, response->head));
+ request_id, new_url, response->head));
}
bool AsyncResourceHandler::OnResponseStarted(int request_id,
@@ -171,16 +170,15 @@ 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.
- ResourceContext* resource_context = filter_->resource_context();
if (rdh_->delegate()) {
rdh_->delegate()->OnResponseStarted(
- request_, resource_context, response, filter_.get());
+ request_, resource_context_, response, filter_.get());
}
DevToolsNetLogObserver::PopulateResponseInfo(request_, response);
HostZoomMap* host_zoom_map =
- GetHostZoomMapForResourceContext(resource_context);
+ GetHostZoomMapForResourceContext(resource_context_);
const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
if (info->GetResourceType() == ResourceType::MAIN_FRAME && host_zoom_map) {
@@ -194,16 +192,14 @@ bool AsyncResourceHandler::OnResponseStarted(int request_id,
response->head.request_start = request_->creation_time();
response->head.response_start = TimeTicks::Now();
- filter_->Send(new ResourceMsg_ReceivedResponse(
- routing_id_, request_id, response->head));
+ 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(
- routing_id_, request_id, copy));
+ filter_->Send(new ResourceMsg_ReceivedCachedMetadata(request_id, copy));
}
return true;
@@ -254,9 +250,8 @@ bool AsyncResourceHandler::OnReadCompleted(int request_id, int bytes_read,
int size;
if (!buffer_->ShareToProcess(filter_->PeerHandle(), &handle, &size))
return false;
- filter_->Send(
- new ResourceMsg_SetDataBuffer(routing_id_, request_id, handle, size,
- filter_->peer_pid()));
+ filter_->Send(new ResourceMsg_SetDataBuffer(
+ request_id, handle, size, filter_->peer_pid()));
sent_first_data_msg_ = true;
}
@@ -264,9 +259,8 @@ bool AsyncResourceHandler::OnReadCompleted(int request_id, int bytes_read,
int encoded_data_length =
DevToolsNetLogObserver::GetAndResetEncodedDataLength(request_);
- filter_->Send(
- new ResourceMsg_DataReceived(routing_id_, request_id, data_offset,
- bytes_read, encoded_data_length));
+ filter_->Send(new ResourceMsg_DataReceived(
+ request_id, data_offset, bytes_read, encoded_data_length));
++pending_data_count_;
UMA_HISTOGRAM_CUSTOM_COUNTS(
"Net.AsyncResourceHandler_PendingDataCount",
@@ -284,8 +278,11 @@ 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_);
+
filter_->Send(new ResourceMsg_DataDownloaded(
- routing_id_, request_id, bytes_downloaded));
+ request_id, bytes_downloaded, encoded_data_length));
}
bool AsyncResourceHandler::OnResponseCompleted(
@@ -328,8 +325,7 @@ bool AsyncResourceHandler::OnResponseCompleted(
error_code = net::ERR_FAILED;
}
- filter_->Send(new ResourceMsg_RequestComplete(routing_id_,
- request_id,
+ filter_->Send(new ResourceMsg_RequestComplete(request_id,
error_code,
was_ignored_by_handler,
security_info,
diff --git a/chromium/content/browser/loader/async_resource_handler.h b/chromium/content/browser/loader/async_resource_handler.h
index 5f36112a9bc..b43e0ef3745 100644
--- a/chromium/content/browser/loader/async_resource_handler.h
+++ b/chromium/content/browser/loader/async_resource_handler.h
@@ -18,6 +18,7 @@ class URLRequest;
namespace content {
class ResourceBuffer;
+class ResourceContext;
class ResourceDispatcherHostImpl;
class ResourceMessageFilter;
class SharedIOBuffer;
@@ -28,7 +29,7 @@ class AsyncResourceHandler : public ResourceHandler,
public ResourceMessageDelegate {
public:
AsyncResourceHandler(ResourceMessageFilter* filter,
- int routing_id,
+ ResourceContext* resource_context,
net::URLRequest* request,
ResourceDispatcherHostImpl* rdh);
virtual ~AsyncResourceHandler();
@@ -75,7 +76,7 @@ class AsyncResourceHandler : public ResourceHandler,
scoped_refptr<ResourceBuffer> buffer_;
scoped_refptr<ResourceMessageFilter> filter_;
- int routing_id_;
+ ResourceContext* resource_context_;
net::URLRequest* request_;
ResourceDispatcherHostImpl* rdh_;
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc b/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc
index cb8896f2e05..0a763fede6c 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc
@@ -15,9 +15,9 @@
#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_utils.h"
-#include "content/shell/shell.h"
-#include "content/shell/shell_content_browser_client.h"
-#include "content/shell/shell_network_delegate.h"
+#include "content/shell/browser/shell.h"
+#include "content/shell/browser/shell_content_browser_client.h"
+#include "content/shell/browser/shell_network_delegate.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
#include "content/test/net/url_request_failed_job.h"
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
index c37137dad89..382a68124b1 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -58,7 +58,6 @@
#include "content/public/browser/download_manager.h"
#include "content/public/browser/download_url_parameters.h"
#include "content/public/browser/global_request_id.h"
-#include "content/public/browser/notification_service.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
#include "content/public/browser/resource_request_details.h"
#include "content/public/browser/resource_throttle.h"
@@ -78,16 +77,17 @@
#include "net/base/upload_data_stream.h"
#include "net/cert/cert_status_flags.h"
#include "net/cookies/cookie_monster.h"
-#include "net/http/http_cache.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
-#include "net/http/http_transaction_factory.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_job_factory.h"
#include "webkit/browser/appcache/appcache_interceptor.h"
-#include "webkit/browser/blob/blob_storage_controller.h"
+#include "webkit/common/blob/blob_data.h"
+#include "webkit/browser/blob/blob_data_handle.h"
+#include "webkit/browser/blob/blob_storage_context.h"
+#include "webkit/browser/blob/blob_url_request_job_factory.h"
#include "webkit/browser/fileapi/file_permission_policy.h"
#include "webkit/browser/fileapi/file_system_context.h"
#include "webkit/common/appcache/appcache_interfaces.h"
@@ -139,7 +139,6 @@ const int kAllNetErrorCodes[] = {
// Aborts a request before an URLRequest has actually been created.
void AbortRequestBeforeItStarts(ResourceMessageFilter* filter,
IPC::Message* sync_result,
- int route_id,
int request_id) {
if (sync_result) {
SyncLoadResult result;
@@ -149,7 +148,6 @@ void AbortRequestBeforeItStarts(ResourceMessageFilter* filter,
} else {
// Tell the renderer that this request was disallowed.
filter->Send(new ResourceMsg_RequestComplete(
- route_id,
request_id,
net::ERR_ABORTED,
false,
@@ -216,11 +214,11 @@ bool ShouldServiceRequest(int process_type,
return false;
}
if (iter->type() == ResourceRequestBody::Element::TYPE_FILE_FILESYSTEM) {
- fileapi::FileSystemURL url = file_system_context->CrackURL(iter->url());
- if (!policy->HasPermissionsForFileSystemFile(
- child_id, url, fileapi::kReadFilePermissions)) {
+ fileapi::FileSystemURL url =
+ file_system_context->CrackURL(iter->filesystem_url());
+ if (!policy->CanReadFileSystemFile(child_id, url)) {
NOTREACHED() << "Denied unauthorized upload of "
- << iter->url().spec();
+ << iter->filesystem_url().spec();
return false;
}
}
@@ -266,17 +264,28 @@ int GetCertID(net::URLRequest* request, int child_id) {
return 0;
}
-template <class T>
-void NotifyOnUI(int type, int render_process_id, int render_view_id,
- scoped_ptr<T> detail) {
+void NotifyRedirectOnUI(int render_process_id,
+ int render_view_id,
+ scoped_ptr<ResourceRedirectDetails> details) {
RenderViewHostImpl* host =
RenderViewHostImpl::FromID(render_process_id, render_view_id);
- if (host) {
- RenderViewHostDelegate* delegate = host->GetDelegate();
- NotificationService::current()->Notify(
- type, Source<WebContents>(delegate->GetAsWebContents()),
- Details<T>(detail.get()));
- }
+ if (!host)
+ return;
+
+ RenderViewHostDelegate* delegate = host->GetDelegate();
+ delegate->DidGetRedirectForResourceRequest(*details.get());
+}
+
+void NotifyResponseOnUI(int render_process_id,
+ int render_view_id,
+ scoped_ptr<ResourceRequestDetails> details) {
+ RenderViewHostImpl* host =
+ RenderViewHostImpl::FromID(render_process_id, render_view_id);
+ if (!host)
+ return;
+
+ RenderViewHostDelegate* delegate = host->GetDelegate();
+ delegate->DidGetResourceResponseStart(*details.get());
}
} // namespace
@@ -502,6 +511,14 @@ net::Error ResourceDispatcherHostImpl::BeginDownload(
CreateRequestInfo(child_id, route_id, true, context);
extra_info->AssociateWithRequest(request.get()); // Request takes ownership.
+ if (request->url().SchemeIs(chrome::kBlobScheme)) {
+ ChromeBlobStorageContext* blob_context =
+ GetChromeBlobStorageContextForResourceContext(context);
+ webkit_blob::BlobProtocolHandler::SetRequestedBlobDataHandle(
+ request.get(),
+ blob_context->context()->GetBlobDataFromPublicURL(request->url()));
+ }
+
// From this point forward, the |DownloadResourceHandler| is responsible for
// |started_callback|.
scoped_ptr<ResourceHandler> handler(
@@ -681,8 +698,7 @@ void ResourceDispatcherHostImpl::DidReceiveRedirect(ResourceLoader* loader,
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(
- &NotifyOnUI<ResourceRedirectDetails>,
- static_cast<int>(NOTIFICATION_RESOURCE_RECEIVED_REDIRECT),
+ &NotifyRedirectOnUI,
render_process_id, render_view_id, base::Passed(&detail)));
}
@@ -713,8 +729,7 @@ void ResourceDispatcherHostImpl::DidReceiveResponse(ResourceLoader* loader) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(
- &NotifyOnUI<ResourceRequestDetails>,
- static_cast<int>(NOTIFICATION_RESOURCE_RESPONSE_STARTED),
+ &NotifyResponseOnUI,
render_process_id, render_view_id, base::Passed(&detail)));
}
@@ -817,8 +832,6 @@ bool ResourceDispatcherHostImpl::OnMessageReceived(
IPC_MESSAGE_HANDLER(ResourceHostMsg_DataDownloaded_ACK, OnDataDownloadedACK)
IPC_MESSAGE_HANDLER(ResourceHostMsg_UploadProgress_ACK, OnUploadProgressACK)
IPC_MESSAGE_HANDLER(ResourceHostMsg_CancelRequest, OnCancelRequest)
- IPC_MESSAGE_HANDLER(ViewHostMsg_DidLoadResourceFromMemoryCache,
- OnDidLoadResourceFromMemoryCache)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP_EX()
@@ -838,12 +851,6 @@ bool ResourceDispatcherHostImpl::OnMessageReceived(
}
}
- if (message.type() == ViewHostMsg_DidLoadResourceFromMemoryCache::ID) {
- // We just needed to peek at this message. We still want it to reach its
- // normal destination.
- handled = false;
- }
-
filter_ = NULL;
return handled;
}
@@ -914,14 +921,16 @@ void ResourceDispatcherHostImpl::BeginRequest(
}
}
- ResourceContext* resource_context = filter_->resource_context();
+ ResourceContext* resource_context = NULL;
+ net::URLRequestContext* request_context = NULL;
+ filter_->GetContexts(request_data, &resource_context, &request_context);
// http://crbug.com/90971
CHECK(ContainsKey(active_resource_contexts_, resource_context));
if (is_shutdown_ ||
!ShouldServiceRequest(process_type, child_id, request_data,
filter_->file_system_context())) {
- AbortRequestBeforeItStarts(filter_, sync_result, route_id, request_id);
+ AbortRequestBeforeItStarts(filter_, sync_result, request_id);
return;
}
@@ -934,7 +943,7 @@ void ResourceDispatcherHostImpl::BeginRequest(
request_data.url,
request_data.resource_type,
resource_context)) {
- AbortRequestBeforeItStarts(filter_, sync_result, route_id, request_id);
+ AbortRequestBeforeItStarts(filter_, sync_result, request_id);
return;
}
@@ -958,9 +967,7 @@ void ResourceDispatcherHostImpl::BeginRequest(
// chance to reset some state before we complete the transfer.
deferred_loader->WillCompleteTransfer();
} else {
- net::URLRequestContext* context =
- filter_->GetURLRequestContext(request_data.resource_type);
- new_request.reset(context->CreateRequest(request_data.url, NULL));
+ new_request.reset(request_context->CreateRequest(request_data.url, NULL));
request = new_request.get();
request->set_method(request_data.method);
@@ -980,9 +987,12 @@ void ResourceDispatcherHostImpl::BeginRequest(
// Resolve elements from request_body and prepare upload data.
if (request_data.request_body.get()) {
+ webkit_blob::BlobStorageContext* blob_context = NULL;
+ if (filter_->blob_storage_context())
+ blob_context = filter_->blob_storage_context()->context();
request->set_upload(UploadDataStreamBuilder::Build(
request_data.request_body.get(),
- filter_->blob_storage_context()->controller(),
+ blob_context,
filter_->file_system_context(),
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)
.get()));
@@ -1017,9 +1027,10 @@ void ResourceDispatcherHostImpl::BeginRequest(
if (request->url().SchemeIs(chrome::kBlobScheme)) {
// Hang on to a reference to ensure the blob is not released prior
// to the job being started.
- extra_info->set_requested_blob_data(
- filter_->blob_storage_context()->controller()->
- GetBlobDataFromUrl(request->url()));
+ webkit_blob::BlobProtocolHandler::SetRequestedBlobDataHandle(
+ request,
+ filter_->blob_storage_context()->context()->
+ GetBlobDataFromPublicURL(request->url()));
}
// Have the appcache associate its extra info with the request.
@@ -1031,10 +1042,10 @@ void ResourceDispatcherHostImpl::BeginRequest(
scoped_ptr<ResourceHandler> handler;
if (sync_result) {
handler.reset(new SyncResourceHandler(
- filter_, request, sync_result, this));
+ filter_, resource_context, request, sync_result, this));
} else {
handler.reset(new AsyncResourceHandler(
- filter_, route_id, request, this));
+ filter_, resource_context, request, this));
}
// The RedirectToFileResourceHandler depends on being next in the chain.
@@ -1184,20 +1195,6 @@ ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo(
true); // is_async
}
-
-void ResourceDispatcherHostImpl::OnDidLoadResourceFromMemoryCache(
- const GURL& url,
- const std::string& security_info,
- const std::string& http_method,
- const std::string& mime_type,
- ResourceType::Type resource_type) {
- if (!url.is_valid() || !(url.SchemeIs("http") || url.SchemeIs("https")))
- return;
-
- filter_->GetURLRequestContext(resource_type)->http_transaction_factory()->
- GetCache()->OnExternalCacheHit(url, http_method);
-}
-
void ResourceDispatcherHostImpl::OnRenderViewHostCreated(
int child_id,
int route_id) {
@@ -1813,7 +1810,7 @@ void ResourceDispatcherHostImpl::UnregisterResourceMessageDelegate(
DelegateMap::iterator it = delegate_map_.find(id);
DCHECK(it->second->HasObserver(delegate));
it->second->RemoveObserver(delegate);
- if (it->second->size() == 0) {
+ if (!it->second->might_have_observers()) {
delete it->second;
delegate_map_.erase(it);
}
@@ -1850,7 +1847,7 @@ int ResourceDispatcherHostImpl::BuildLoadFlagsForRequest(
HttpAuthRelationType relation_type = HttpAuthRelationTypeOf(
request_data.url, request_data.first_party_for_cookies);
if (relation_type == HTTP_AUTH_RELATION_BLOCKED_CROSS) {
- load_flags |= (net::LOAD_DO_NOT_SEND_AUTH_DATA |
+ load_flags |= (net::LOAD_DO_NOT_USE_EMBEDDED_IDENTITY |
net::LOAD_DO_NOT_PROMPT_FOR_LOGIN);
}
}
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.h b/chromium/content/browser/loader/resource_dispatcher_host_impl.h
index af53b70ce75..e6f2241d9a0 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_impl.h
+++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.h
@@ -162,13 +162,6 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
return save_file_manager_.get();
}
- // Called when the renderer loads a resource from its internal cache.
- void OnDidLoadResourceFromMemoryCache(const GURL& url,
- const std::string& security_info,
- const std::string& http_method,
- const std::string& mime_type,
- ResourceType::Type resource_type);
-
// Called when a RenderViewHost is created.
void OnRenderViewHostCreated(int child_id, int route_id);
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc b/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
index be463398f8d..89b17c44c73 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -159,22 +159,6 @@ void ResourceIPCAccumulator::GetClassifiedMessages(ClassifiedMessages* msgs) {
}
}
-class MockURLRequestContextSelector
- : public ResourceMessageFilter::URLRequestContextSelector {
- public:
- explicit MockURLRequestContextSelector(
- net::URLRequestContext* request_context)
- : request_context_(request_context) {}
-
- virtual net::URLRequestContext* GetRequestContext(
- ResourceType::Type request_type) OVERRIDE {
- return request_context_;
- }
-
- private:
- net::URLRequestContext* const request_context_;
-};
-
// This class forwards the incoming messages to the ResourceDispatcherHostTest.
// This is used to emulate different sub-processes, since this filter will
// have a different ID than the original. For the test, we want all the incoming
@@ -185,11 +169,11 @@ class ForwardingFilter : public ResourceMessageFilter {
ResourceContext* resource_context)
: ResourceMessageFilter(
ChildProcessHostImpl::GenerateChildProcessUniqueId(),
- PROCESS_TYPE_RENDERER,
- resource_context, NULL, NULL, NULL,
- new MockURLRequestContextSelector(
- resource_context->GetRequestContext())),
- dest_(dest) {
+ PROCESS_TYPE_RENDERER, NULL, NULL, NULL,
+ base::Bind(&ForwardingFilter::GetContexts,
+ base::Unretained(this))),
+ dest_(dest),
+ resource_context_(resource_context) {
OnChannelConnected(base::GetCurrentProcId());
}
@@ -200,11 +184,21 @@ class ForwardingFilter : public ResourceMessageFilter {
return dest_->Send(msg);
}
+ ResourceContext* resource_context() { return resource_context_; }
+
protected:
virtual ~ForwardingFilter() {}
private:
+ void GetContexts(const ResourceHostMsg_Request& request,
+ ResourceContext** resource_context,
+ net::URLRequestContext** request_context) {
+ *resource_context = resource_context_;
+ *request_context = resource_context_->GetRequestContext();
+ }
+
IPC::Sender* dest_;
+ ResourceContext* resource_context_;
DISALLOW_COPY_AND_ASSIGN(ForwardingFilter);
};
@@ -708,7 +702,7 @@ class ResourceDispatcherHostTest : public testing::Test,
bool result = PickleIterator(msg).ReadInt(&request_id);
DCHECK(result);
scoped_ptr<IPC::Message> ack(
- new ResourceHostMsg_DataReceived_ACK(msg.routing_id(), request_id));
+ new ResourceHostMsg_DataReceived_ACK(request_id));
base::MessageLoop::current()->PostTask(
FROM_HERE,
@@ -1609,7 +1603,7 @@ TEST_F(ResourceDispatcherHostTest, IgnoreCancelForDownloads) {
EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
// And now simulate a cancellation coming from the renderer.
- ResourceHostMsg_CancelRequest msg(filter_->child_id(), request_id);
+ ResourceHostMsg_CancelRequest msg(request_id);
bool msg_was_ok;
host_.OnMessageReceived(msg, filter_.get(), &msg_was_ok);
@@ -1644,7 +1638,7 @@ TEST_F(ResourceDispatcherHostTest, CancelRequestsForContext) {
EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
// And now simulate a cancellation coming from the renderer.
- ResourceHostMsg_CancelRequest msg(filter_->child_id(), request_id);
+ ResourceHostMsg_CancelRequest msg(request_id);
bool msg_was_ok;
host_.OnMessageReceived(msg, filter_.get(), &msg_was_ok);
@@ -1685,7 +1679,7 @@ TEST_F(ResourceDispatcherHostTest, CancelRequestsForContextTransferred) {
GURL("http://example.com/blah"));
// And now simulate a cancellation coming from the renderer.
- ResourceHostMsg_CancelRequest msg(filter_->child_id(), request_id);
+ ResourceHostMsg_CancelRequest msg(request_id);
bool msg_was_ok;
host_.OnMessageReceived(msg, filter_.get(), &msg_was_ok);
@@ -1832,7 +1826,7 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationAndThenRedirect) {
// Now, simulate the renderer choosing to follow the redirect.
ResourceHostMsg_FollowRedirect redirect_msg(
- new_render_view_id, new_request_id, false, GURL());
+ new_request_id, false, GURL());
host_.OnMessageReceived(redirect_msg, second_filter.get(), &msg_was_ok);
base::MessageLoop::current()->RunUntilIdle();
@@ -1938,7 +1932,7 @@ TEST_F(ResourceDispatcherHostTest, DelayedDataReceivedACKs) {
EXPECT_EQ(ResourceMsg_DataReceived::ID, msgs[0][i].type());
- ResourceHostMsg_DataReceived_ACK msg(0, 1);
+ ResourceHostMsg_DataReceived_ACK msg(1);
bool msg_was_ok;
host_.OnMessageReceived(msg, filter_.get(), &msg_was_ok);
}
@@ -1973,7 +1967,7 @@ TEST_F(ResourceDispatcherHostTest, DataReceivedUnexpectedACKs) {
// Send some unexpected ACKs.
for (size_t i = 0; i < 128; ++i) {
- ResourceHostMsg_DataReceived_ACK msg(0, 1);
+ ResourceHostMsg_DataReceived_ACK msg(1);
bool msg_was_ok;
host_.OnMessageReceived(msg, filter_.get(), &msg_was_ok);
}
@@ -1992,7 +1986,7 @@ TEST_F(ResourceDispatcherHostTest, DataReceivedUnexpectedACKs) {
EXPECT_EQ(ResourceMsg_DataReceived::ID, msgs[0][i].type());
- ResourceHostMsg_DataReceived_ACK msg(0, 1);
+ ResourceHostMsg_DataReceived_ACK msg(1);
bool msg_was_ok;
host_.OnMessageReceived(msg, filter_.get(), &msg_was_ok);
}
diff --git a/chromium/content/browser/loader/resource_message_filter.cc b/chromium/content/browser/loader/resource_message_filter.cc
index 7c523975fba..26ba80fbaa4 100644
--- a/chromium/content/browser/loader/resource_message_filter.cc
+++ b/chromium/content/browser/loader/resource_message_filter.cc
@@ -15,21 +15,16 @@ namespace content {
ResourceMessageFilter::ResourceMessageFilter(
int child_id,
int process_type,
- ResourceContext* resource_context,
ChromeAppCacheService* appcache_service,
ChromeBlobStorageContext* blob_storage_context,
fileapi::FileSystemContext* file_system_context,
- URLRequestContextSelector* url_request_context_selector)
+ const GetContextsCallback& get_contexts_callback)
: child_id_(child_id),
process_type_(process_type),
- resource_context_(resource_context),
appcache_service_(appcache_service),
blob_storage_context_(blob_storage_context),
file_system_context_(file_system_context),
- url_request_context_selector_(url_request_context_selector) {
- DCHECK(resource_context);
- DCHECK(url_request_context_selector);
- // |appcache_service| and |blob_storage_context| may be NULL in unittests.
+ get_contexts_callback_(get_contexts_callback) {
}
ResourceMessageFilter::~ResourceMessageFilter() {
@@ -49,9 +44,11 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& message,
message, this, message_was_ok);
}
-net::URLRequestContext* ResourceMessageFilter::GetURLRequestContext(
- ResourceType::Type type) {
- return url_request_context_selector_->GetRequestContext(type);
+void ResourceMessageFilter::GetContexts(
+ const ResourceHostMsg_Request& request,
+ ResourceContext** resource_context,
+ net::URLRequestContext** request_context) {
+ return get_contexts_callback_.Run(request, resource_context, request_context);
}
} // namespace content
diff --git a/chromium/content/browser/loader/resource_message_filter.h b/chromium/content/browser/loader/resource_message_filter.h
index 2c56af0dd6d..925e4525e28 100644
--- a/chromium/content/browser/loader/resource_message_filter.h
+++ b/chromium/content/browser/loader/resource_message_filter.h
@@ -5,11 +5,14 @@
#ifndef CONTENT_BROWSER_LOADER_RESOURCE_MESSAGE_FILTER_H_
#define CONTENT_BROWSER_LOADER_RESOURCE_MESSAGE_FILTER_H_
+#include "base/callback_forward.h"
#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_message_filter.h"
#include "webkit/common/resource_type.h"
+struct ResourceHostMsg_Request;
+
namespace fileapi {
class FileSystemContext;
} // namespace fileapi
@@ -31,36 +34,32 @@ class ResourceContext;
// will not interfere with browser UI.
class CONTENT_EXPORT ResourceMessageFilter : public BrowserMessageFilter {
public:
- // Allows selecting the net::URLRequestContext used to service requests.
- class URLRequestContextSelector {
- public:
- URLRequestContextSelector() {}
- virtual ~URLRequestContextSelector() {}
-
- virtual net::URLRequestContext* GetRequestContext(
- ResourceType::Type request_type) = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(URLRequestContextSelector);
- };
+ typedef base::Callback<void(const ResourceHostMsg_Request&,
+ ResourceContext**,
+ net::URLRequestContext**)> GetContextsCallback;
+ // |appcache_service|, |blob_storage_context|, |file_system_context| may be
+ // NULL in unittests or for requests from the (NPAPI) plugin process.
ResourceMessageFilter(
int child_id,
int process_type,
- ResourceContext* resource_context,
ChromeAppCacheService* appcache_service,
ChromeBlobStorageContext* blob_storage_context,
fileapi::FileSystemContext* file_system_context,
- URLRequestContextSelector* url_request_context_selector);
+ const GetContextsCallback& get_contexts_callback);
// BrowserMessageFilter implementation.
virtual void OnChannelClosing() OVERRIDE;
virtual bool OnMessageReceived(const IPC::Message& message,
bool* message_was_ok) OVERRIDE;
- ResourceContext* resource_context() const {
- return resource_context_;
- }
+ void GetContexts(const ResourceHostMsg_Request& request,
+ ResourceContext** resource_context,
+ net::URLRequestContext** request_context);
+
+ // Returns the net::URLRequestContext for the given request.
+ net::URLRequestContext* GetURLRequestContext(
+ ResourceType::Type request_type);
ChromeAppCacheService* appcache_service() const {
return appcache_service_.get();
@@ -74,10 +73,6 @@ class CONTENT_EXPORT ResourceMessageFilter : public BrowserMessageFilter {
return file_system_context_.get();
}
- // Returns the net::URLRequestContext for the given request.
- net::URLRequestContext* GetURLRequestContext(
- ResourceType::Type request_type);
-
int child_id() const { return child_id_; }
int process_type() const { return process_type_; }
@@ -91,14 +86,11 @@ class CONTENT_EXPORT ResourceMessageFilter : public BrowserMessageFilter {
int process_type_;
- // Owned by ProfileIOData* which is guaranteed to outlive us.
- ResourceContext* resource_context_;
-
scoped_refptr<ChromeAppCacheService> appcache_service_;
scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
scoped_refptr<fileapi::FileSystemContext> file_system_context_;
- const scoped_ptr<URLRequestContextSelector> url_request_context_selector_;
+ GetContextsCallback get_contexts_callback_;
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 51e39ff3ddd..c41fe39e565 100644
--- a/chromium/content/browser/loader/resource_request_info_impl.cc
+++ b/chromium/content/browser/loader/resource_request_info_impl.cc
@@ -9,7 +9,6 @@
#include "content/common/net/url_request_user_data.h"
#include "content/public/browser/global_request_id.h"
#include "net/url_request/url_request.h"
-#include "webkit/common/blob/blob_data.h"
namespace content {
@@ -196,6 +195,9 @@ bool ResourceRequestInfoImpl::GetAssociatedRenderView(
*render_view_id = -1;
return false;
}
+ } else if (process_type_ == PROCESS_TYPE_PLUGIN) {
+ *render_process_id = origin_pid_;
+ *render_view_id = route_id_;
} else {
*render_process_id = child_id_;
*render_view_id = route_id_;
@@ -226,9 +228,4 @@ GlobalRoutingID ResourceRequestInfoImpl::GetGlobalRoutingID() const {
return GlobalRoutingID(child_id_, route_id_);
}
-void ResourceRequestInfoImpl::set_requested_blob_data(
- webkit_blob::BlobData* data) {
- requested_blob_data_ = data;
-}
-
} // 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 d99586530ab..e615116c152 100644
--- a/chromium/content/browser/loader/resource_request_info_impl.h
+++ b/chromium/content/browser/loader/resource_request_info_impl.h
@@ -16,10 +16,6 @@
#include "net/base/load_states.h"
#include "webkit/common/resource_type.h"
-namespace webkit_blob {
-class BlobData;
-}
-
namespace content {
class CrossSiteResourceHandler;
class ResourceContext;
@@ -116,13 +112,6 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
int memory_cost() const { return memory_cost_; }
void set_memory_cost(int cost) { memory_cost_ = cost; }
- // We hold a reference to the requested blob data to ensure it doesn't
- // get finally released prior to the net::URLRequestJob being started.
- webkit_blob::BlobData* requested_blob_data() const {
- return requested_blob_data_.get();
- }
- void set_requested_blob_data(webkit_blob::BlobData* data);
-
private:
// Non-owning, may be NULL.
CrossSiteResourceHandler* cross_site_handler_;
@@ -144,7 +133,6 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
ResourceType::Type resource_type_;
PageTransition transition_type_;
int memory_cost_;
- scoped_refptr<webkit_blob::BlobData> requested_blob_data_;
WebKit::WebReferrerPolicy referrer_policy_;
ResourceContext* context_;
bool is_async_;
diff --git a/chromium/content/browser/loader/resource_scheduler.cc b/chromium/content/browser/loader/resource_scheduler.cc
index 7e70c457814..0277783bfdf 100644
--- a/chromium/content/browser/loader/resource_scheduler.cc
+++ b/chromium/content/browser/loader/resource_scheduler.cc
@@ -81,6 +81,8 @@ class ResourceScheduler::ScheduledResourceRequest
ready_(false),
deferred_(false),
scheduler_(scheduler) {
+ TRACE_EVENT_ASYNC_BEGIN1("net", "URLRequest", request_,
+ "url", request->url().spec());
}
virtual ~ScheduledResourceRequest() {
@@ -88,6 +90,7 @@ class ResourceScheduler::ScheduledResourceRequest
}
void Start() {
+ TRACE_EVENT_ASYNC_STEP0("net", "URLRequest", request_, "Queued");
ready_ = true;
if (deferred_ && request_->status().is_success()) {
deferred_ = false;
diff --git a/chromium/content/browser/loader/resource_scheduler_unittest.cc b/chromium/content/browser/loader/resource_scheduler_unittest.cc
index 9d87f2df047..2c4c1101962 100644
--- a/chromium/content/browser/loader/resource_scheduler_unittest.cc
+++ b/chromium/content/browser/loader/resource_scheduler_unittest.cc
@@ -93,30 +93,29 @@ class FakeResourceContext : public ResourceContext {
virtual bool AllowCameraAccess(const GURL& origin) OVERRIDE { return false; }
};
-class FakeURLRequestContextSelector
- : public ResourceMessageFilter::URLRequestContextSelector {
- private:
- virtual net::URLRequestContext* GetRequestContext(
- ResourceType::Type) OVERRIDE {
- return NULL;
- }
-};
-
class FakeResourceMessageFilter : public ResourceMessageFilter {
public:
FakeResourceMessageFilter(int child_id)
- : ResourceMessageFilter(child_id,
- PROCESS_TYPE_RENDERER,
- &context_,
- NULL /* appcache_service */,
- NULL /* blob_storage_context */,
- NULL /* file_system_context */,
- new FakeURLRequestContextSelector) {
+ : ResourceMessageFilter(
+ child_id,
+ PROCESS_TYPE_RENDERER,
+ NULL /* appcache_service */,
+ NULL /* blob_storage_context */,
+ NULL /* file_system_context */,
+ base::Bind(&FakeResourceMessageFilter::GetContexts,
+ base::Unretained(this))) {
}
private:
virtual ~FakeResourceMessageFilter() {}
+ void GetContexts(const ResourceHostMsg_Request& request,
+ ResourceContext** resource_context,
+ net::URLRequestContext** request_context) {
+ *resource_context = &context_;
+ *request_context = NULL;
+ }
+
FakeResourceContext context_;
};
@@ -193,8 +192,7 @@ class ResourceSchedulerTest : public testing::Test {
const ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(
request->url_request());
const GlobalRequestID& id = info->GetGlobalRequestID();
- ResourceHostMsg_DidChangePriority msg(
- kRouteId, id.request_id, new_priority);
+ ResourceHostMsg_DidChangePriority msg(id.request_id, new_priority);
bool ok = false;
rdh_.OnMessageReceived(msg, filter.get(), &ok);
EXPECT_TRUE(ok);
diff --git a/chromium/content/browser/loader/sync_resource_handler.cc b/chromium/content/browser/loader/sync_resource_handler.cc
index 1db8dca79b0..b1a71622c2b 100644
--- a/chromium/content/browser/loader/sync_resource_handler.cc
+++ b/chromium/content/browser/loader/sync_resource_handler.cc
@@ -18,11 +18,13 @@ 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),
result_message_(result_message),
rdh_(resource_dispatcher_host) {
@@ -48,9 +50,8 @@ bool SyncResourceHandler::OnRequestRedirected(
ResourceResponse* response,
bool* defer) {
if (rdh_->delegate()) {
- rdh_->delegate()->OnRequestRedirected(new_url, request_,
- filter_->resource_context(),
- response);
+ rdh_->delegate()->OnRequestRedirected(
+ new_url, request_, resource_context_, response);
}
DevToolsNetLogObserver::PopulateResponseInfo(request_, response);
@@ -71,7 +72,7 @@ bool SyncResourceHandler::OnResponseStarted(
bool* defer) {
if (rdh_->delegate()) {
rdh_->delegate()->OnResponseStarted(
- request_, filter_->resource_context(), response, filter_.get());
+ request_, resource_context_, response, filter_.get());
}
DevToolsNetLogObserver::PopulateResponseInfo(request_, response);
diff --git a/chromium/content/browser/loader/sync_resource_handler.h b/chromium/content/browser/loader/sync_resource_handler.h
index af254729332..838a05a225c 100644
--- a/chromium/content/browser/loader/sync_resource_handler.h
+++ b/chromium/content/browser/loader/sync_resource_handler.h
@@ -20,6 +20,7 @@ class URLRequest;
}
namespace content {
+class ResourceContext;
class ResourceDispatcherHostImpl;
class ResourceMessageFilter;
@@ -28,6 +29,7 @@ class ResourceMessageFilter;
class SyncResourceHandler : public ResourceHandler {
public:
SyncResourceHandler(ResourceMessageFilter* filter,
+ ResourceContext* resource_context,
net::URLRequest* request,
IPC::Message* result_message,
ResourceDispatcherHostImpl* resource_dispatcher_host);
@@ -65,6 +67,7 @@ class SyncResourceHandler : public ResourceHandler {
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/upload_data_stream_builder.cc b/chromium/content/browser/loader/upload_data_stream_builder.cc
index 1a7dfc33e09..c22a8a8d444 100644
--- a/chromium/content/browser/loader/upload_data_stream_builder.cc
+++ b/chromium/content/browser/loader/upload_data_stream_builder.cc
@@ -8,12 +8,14 @@
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_data_stream.h"
#include "net/base/upload_file_element_reader.h"
-#include "webkit/browser/blob/blob_storage_controller.h"
+#include "webkit/browser/blob/blob_data_handle.h"
+#include "webkit/browser/blob/blob_storage_context.h"
#include "webkit/browser/fileapi/upload_file_system_file_element_reader.h"
#include "webkit/common/resource_request_body.h"
using webkit_blob::BlobData;
-using webkit_blob::BlobStorageController;
+using webkit_blob::BlobDataHandle;
+using webkit_blob::BlobStorageContext;
using webkit_glue::ResourceRequestBody;
namespace content {
@@ -64,49 +66,51 @@ class FileElementReader : public net::UploadFileElementReader {
void ResolveBlobReference(
ResourceRequestBody* body,
- webkit_blob::BlobStorageController* blob_controller,
- const GURL& blob_url,
+ webkit_blob::BlobStorageContext* blob_context,
+ const ResourceRequestBody::Element& element,
std::vector<const ResourceRequestBody::Element*>* resolved_elements) {
- DCHECK(blob_controller);
- BlobData* blob_data = blob_controller->GetBlobDataFromUrl(blob_url);
- DCHECK(blob_data);
- if (!blob_data)
+ 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);
+ DCHECK(handle);
+ if (!handle)
return;
// If there is no element in the referred blob data, just return.
- if (blob_data->items().empty())
+ if (handle->data()->items().empty())
return;
- // Ensure the blob and any attached shareable files survive until
- // upload completion.
- body->SetUserData(blob_data, new base::UserDataAdapter<BlobData>(blob_data));
-
- // Append the elements in the referred blob data.
- for (size_t i = 0; i < blob_data->items().size(); ++i) {
- const BlobData::Item& item = blob_data->items().at(i);
+ // Append the elements in the referenced blob data.
+ for (size_t i = 0; i < handle->data()->items().size(); ++i) {
+ const BlobData::Item& item = handle->data()->items().at(i);
DCHECK_NE(BlobData::Item::TYPE_BLOB, item.type());
resolved_elements->push_back(&item);
}
+
+ // Ensure the blob and any attached shareable files survive until
+ // upload completion. The |body| takes ownership of |handle|.
+ const void* key = handle.get();
+ body->SetUserData(key, handle.release());
}
} // namespace
scoped_ptr<net::UploadDataStream> UploadDataStreamBuilder::Build(
ResourceRequestBody* body,
- BlobStorageController* blob_controller,
+ BlobStorageContext* blob_context,
fileapi::FileSystemContext* file_system_context,
base::TaskRunner* file_task_runner) {
// Resolve all blob elements.
std::vector<const ResourceRequestBody::Element*> resolved_elements;
for (size_t i = 0; i < body->elements()->size(); ++i) {
const ResourceRequestBody::Element& element = (*body->elements())[i];
- if (element.type() == ResourceRequestBody::Element::TYPE_BLOB) {
- ResolveBlobReference(body, blob_controller, element.url(),
- &resolved_elements);
- } else {
- // No need to resolve, just append the element.
+ if (element.type() == ResourceRequestBody::Element::TYPE_BLOB)
+ ResolveBlobReference(body, blob_context, element, &resolved_elements);
+ else
resolved_elements.push_back(&element);
- }
}
ScopedVector<net::UploadElementReader> element_readers;
@@ -124,7 +128,7 @@ scoped_ptr<net::UploadDataStream> UploadDataStreamBuilder::Build(
element_readers.push_back(
new fileapi::UploadFileSystemFileElementReader(
file_system_context,
- element.url(),
+ element.filesystem_url(),
element.offset(),
element.length(),
element.expected_modification_time()));
diff --git a/chromium/content/browser/loader/upload_data_stream_builder.h b/chromium/content/browser/loader/upload_data_stream_builder.h
index b5115466565..e2b6ce3fc29 100644
--- a/chromium/content/browser/loader/upload_data_stream_builder.h
+++ b/chromium/content/browser/loader/upload_data_stream_builder.h
@@ -21,7 +21,7 @@ class UploadDataStream;
}
namespace webkit_blob {
-class BlobStorageController;
+class BlobStorageContext;
}
namespace webkit_glue {
@@ -34,7 +34,7 @@ class CONTENT_EXPORT UploadDataStreamBuilder {
public:
// Creates a new UploadDataStream from this request body.
//
- // This also resolves any blob references using the given |blob_controller|
+ // This also resolves any blob references using the given |blob_context|
// and binds those blob references to the ResourceRequestBody ensuring that
// the blob data remains valid for the lifetime of the ResourceRequestBody
// object.
@@ -44,7 +44,7 @@ class CONTENT_EXPORT UploadDataStreamBuilder {
// when the data gets uploaded.
static scoped_ptr<net::UploadDataStream> Build(
webkit_glue::ResourceRequestBody* body,
- webkit_blob::BlobStorageController* blob_controller,
+ webkit_blob::BlobStorageContext* blob_context,
fileapi::FileSystemContext* file_system_context,
base::TaskRunner* file_task_runner);
};
diff --git a/chromium/content/browser/loader/upload_data_stream_builder_unittest.cc b/chromium/content/browser/loader/upload_data_stream_builder_unittest.cc
index 9972418a06d..4c9661cbee6 100644
--- a/chromium/content/browser/loader/upload_data_stream_builder_unittest.cc
+++ b/chromium/content/browser/loader/upload_data_stream_builder_unittest.cc
@@ -16,11 +16,12 @@
#include "net/base/upload_file_element_reader.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
-#include "webkit/browser/blob/blob_storage_controller.h"
+#include "webkit/browser/blob/blob_storage_context.h"
#include "webkit/common/resource_request_body.h"
using webkit_blob::BlobData;
-using webkit_blob::BlobStorageController;
+using webkit_blob::BlobDataHandle;
+using webkit_blob::BlobStorageContext;
using webkit_glue::ResourceRequestBody;
namespace content {
@@ -98,24 +99,20 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) {
base::Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT", &time1);
base::Time::FromString("Mon, 14 Nov 1994, 11:30:49 GMT", &time2);
- BlobStorageController blob_storage_controller;
- scoped_refptr<BlobData> blob_data(new BlobData());
+ BlobStorageContext blob_storage_context;
- GURL blob_url0("blob://url_0");
- blob_storage_controller.AddFinishedBlob(blob_url0, blob_data.get());
+ const std::string blob_id0("id-0");
+ scoped_refptr<BlobData> blob_data(new BlobData(blob_id0));
+ scoped_ptr<BlobDataHandle> handle1 =
+ blob_storage_context.AddFinishedBlob(blob_data);
+ const std::string blob_id1("id-1");
+ blob_data = new BlobData(blob_id1);
blob_data->AppendData("BlobData");
blob_data->AppendFile(
base::FilePath(FILE_PATH_LITERAL("BlobFile.txt")), 0, 20, time1);
-
- GURL blob_url1("blob://url_1");
- blob_storage_controller.AddFinishedBlob(blob_url1, blob_data.get());
-
- GURL blob_url2("blob://url_2");
- blob_storage_controller.CloneBlob(blob_url2, blob_url1);
-
- GURL blob_url3("blob://url_3");
- blob_storage_controller.CloneBlob(blob_url3, blob_url2);
+ scoped_ptr<BlobDataHandle> handle2 =
+ blob_storage_context.AddFinishedBlob(blob_data);
// Setup upload data elements for comparison.
ResourceRequestBody::Element blob_element1, blob_element2;
@@ -144,7 +141,7 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) {
scoped_ptr<net::UploadDataStream> upload(
UploadDataStreamBuilder::Build(request_body.get(),
- &blob_storage_controller,
+ &blob_storage_context,
NULL,
base::MessageLoopProxy::current().get()));
@@ -154,22 +151,22 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) {
// Test having only one blob reference that refers to empty blob data.
request_body = new ResourceRequestBody();
- request_body->AppendBlob(blob_url0);
+ request_body->AppendBlob(blob_id0);
upload =
UploadDataStreamBuilder::Build(request_body.get(),
- &blob_storage_controller,
+ &blob_storage_context,
NULL,
base::MessageLoopProxy::current().get());
ASSERT_EQ(0U, upload->element_readers().size());
// Test having only one blob reference.
request_body = new ResourceRequestBody();
- request_body->AppendBlob(blob_url1);
+ request_body->AppendBlob(blob_id1);
upload =
UploadDataStreamBuilder::Build(request_body.get(),
- &blob_storage_controller,
+ &blob_storage_context,
NULL,
base::MessageLoopProxy::current().get());
ASSERT_EQ(2U, upload->element_readers().size());
@@ -178,7 +175,7 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) {
// Test having one blob reference at the beginning.
request_body = new ResourceRequestBody();
- request_body->AppendBlob(blob_url1);
+ request_body->AppendBlob(blob_id1);
request_body->AppendBytes(upload_element1.bytes(), upload_element1.length());
request_body->AppendFileRange(upload_element2.path(),
upload_element2.offset(),
@@ -187,7 +184,7 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) {
upload =
UploadDataStreamBuilder::Build(request_body.get(),
- &blob_storage_controller,
+ &blob_storage_context,
NULL,
base::MessageLoopProxy::current().get());
ASSERT_EQ(4U, upload->element_readers().size());
@@ -203,11 +200,11 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) {
upload_element2.offset(),
upload_element2.length(),
upload_element2.expected_modification_time());
- request_body->AppendBlob(blob_url1);
+ request_body->AppendBlob(blob_id1);
upload =
UploadDataStreamBuilder::Build(request_body.get(),
- &blob_storage_controller,
+ &blob_storage_context,
NULL,
base::MessageLoopProxy::current().get());
ASSERT_EQ(4U, upload->element_readers().size());
@@ -219,7 +216,7 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) {
// Test having one blob reference in the middle.
request_body = new ResourceRequestBody();
request_body->AppendBytes(upload_element1.bytes(), upload_element1.length());
- request_body->AppendBlob(blob_url1);
+ request_body->AppendBlob(blob_id1);
request_body->AppendFileRange(upload_element2.path(),
upload_element2.offset(),
upload_element2.length(),
@@ -227,7 +224,7 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) {
upload =
UploadDataStreamBuilder::Build(request_body.get(),
- &blob_storage_controller,
+ &blob_storage_context,
NULL,
base::MessageLoopProxy::current().get());
ASSERT_EQ(4U, upload->element_readers().size());
@@ -238,10 +235,10 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) {
// Test having multiple blob references.
request_body = new ResourceRequestBody();
- request_body->AppendBlob(blob_url1);
+ request_body->AppendBlob(blob_id1);
request_body->AppendBytes(upload_element1.bytes(), upload_element1.length());
- request_body->AppendBlob(blob_url2);
- request_body->AppendBlob(blob_url3);
+ request_body->AppendBlob(blob_id1);
+ request_body->AppendBlob(blob_id1);
request_body->AppendFileRange(upload_element2.path(),
upload_element2.offset(),
upload_element2.length(),
@@ -249,7 +246,7 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) {
upload =
UploadDataStreamBuilder::Build(request_body.get(),
- &blob_storage_controller,
+ &blob_storage_context,
NULL,
base::MessageLoopProxy::current().get());
ASSERT_EQ(8U, upload->element_readers().size());
diff --git a/chromium/content/browser/media/android/OWNERS b/chromium/content/browser/media/android/OWNERS
new file mode 100644
index 00000000000..5abf5a186b9
--- /dev/null
+++ b/chromium/content/browser/media/android/OWNERS
@@ -0,0 +1 @@
+qinmin@chromium.org
diff --git a/chromium/content/browser/media/android/browser_demuxer_android.cc b/chromium/content/browser/media/android/browser_demuxer_android.cc
new file mode 100644
index 00000000000..229b8858f1f
--- /dev/null
+++ b/chromium/content/browser/media/android/browser_demuxer_android.cc
@@ -0,0 +1,111 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/android/browser_demuxer_android.h"
+
+#include "content/common/media/media_player_messages_android.h"
+
+namespace content {
+
+BrowserDemuxerAndroid::BrowserDemuxerAndroid() {}
+
+BrowserDemuxerAndroid::~BrowserDemuxerAndroid() {}
+
+void BrowserDemuxerAndroid::OverrideThreadForMessage(
+ const IPC::Message& message,
+ BrowserThread::ID* thread) {
+ switch (message.type()) {
+ case MediaPlayerHostMsg_DemuxerReady::ID:
+ case MediaPlayerHostMsg_ReadFromDemuxerAck::ID:
+ case MediaPlayerHostMsg_DurationChanged::ID:
+ case MediaPlayerHostMsg_MediaSeekRequestAck::ID:
+ *thread = BrowserThread::UI;
+ return;
+ }
+}
+
+bool BrowserDemuxerAndroid::OnMessageReceived(const IPC::Message& message,
+ bool* message_was_ok) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP_EX(BrowserDemuxerAndroid, message, *message_was_ok)
+ IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DemuxerReady, OnDemuxerReady)
+ IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_ReadFromDemuxerAck,
+ OnReadFromDemuxerAck)
+ IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DurationChanged,
+ OnDurationChanged)
+ IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaSeekRequestAck,
+ OnMediaSeekRequestAck)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void BrowserDemuxerAndroid::AddDemuxerClient(
+ int demuxer_client_id,
+ media::DemuxerAndroidClient* client) {
+ DVLOG(1) << __FUNCTION__ << " peer_pid=" << peer_pid()
+ << " demuxer_client_id=" << demuxer_client_id;
+ demuxer_clients_.AddWithID(client, demuxer_client_id);
+}
+
+void BrowserDemuxerAndroid::RemoveDemuxerClient(int demuxer_client_id) {
+ DVLOG(1) << __FUNCTION__ << " peer_pid=" << peer_pid()
+ << " demuxer_client_id=" << 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) {
+ media::DemuxerAndroidClient* client =
+ demuxer_clients_.Lookup(demuxer_client_id);
+ if (client)
+ client->OnDemuxerConfigsAvailable(configs);
+}
+
+void BrowserDemuxerAndroid::OnReadFromDemuxerAck(
+ int demuxer_client_id,
+ const media::DemuxerData& data) {
+ media::DemuxerAndroidClient* client =
+ demuxer_clients_.Lookup(demuxer_client_id);
+ if (client)
+ client->OnDemuxerDataAvailable(data);
+}
+
+void BrowserDemuxerAndroid::OnMediaSeekRequestAck(int demuxer_client_id,
+ unsigned seek_request_id) {
+ media::DemuxerAndroidClient* client =
+ demuxer_clients_.Lookup(demuxer_client_id);
+ if (client)
+ client->OnDemuxerSeeked(seek_request_id);
+}
+
+void BrowserDemuxerAndroid::OnDurationChanged(int demuxer_client_id,
+ const base::TimeDelta& duration) {
+ media::DemuxerAndroidClient* client =
+ demuxer_clients_.Lookup(demuxer_client_id);
+ if (client)
+ client->OnDemuxerDurationChanged(duration);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/android/browser_demuxer_android.h b/chromium/content/browser/media/android/browser_demuxer_android.h
new file mode 100644
index 00000000000..6d17428f2d9
--- /dev/null
+++ b/chromium/content/browser/media/android/browser_demuxer_android.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_MEDIA_ANDROID_BROWSER_DEMUXER_ANDROID_H_
+#define CONTENT_BROWSER_MEDIA_ANDROID_BROWSER_DEMUXER_ANDROID_H_
+
+#include "base/id_map.h"
+#include "content/public/browser/browser_message_filter.h"
+#include "media/base/android/demuxer_android.h"
+
+namespace content {
+
+// Represents the browser process half of an IPC-based implementation of
+// media::DemuxerAndroid.
+//
+// Refer to RendererDemuxerAndroid for the renderer process half.
+class CONTENT_EXPORT BrowserDemuxerAndroid
+ : public BrowserMessageFilter,
+ public media::DemuxerAndroid {
+ public:
+ BrowserDemuxerAndroid();
+
+ // BrowserMessageFilter overrides.
+ virtual void OverrideThreadForMessage(const IPC::Message& message,
+ BrowserThread::ID* thread) OVERRIDE;
+ 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;
+
+ protected:
+ friend class base::RefCountedThreadSafe<BrowserDemuxerAndroid>;
+ virtual ~BrowserDemuxerAndroid();
+
+ private:
+ 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 OnDurationChanged(int demuxer_client_id,
+ const base::TimeDelta& duration);
+
+ IDMap<media::DemuxerAndroidClient> demuxer_clients_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserDemuxerAndroid);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_ANDROID_BROWSER_DEMUXER_ANDROID_H_
diff --git a/chromium/content/browser/android/browser_media_player_manager.cc b/chromium/content/browser/media/android/browser_media_player_manager.cc
index dbf0c8f303d..f0129c13b24 100644
--- a/chromium/content/browser/android/browser_media_player_manager.cc
+++ b/chromium/content/browser/media/android/browser_media_player_manager.cc
@@ -2,10 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/android/browser_media_player_manager.h"
+#include "content/browser/media/android/browser_media_player_manager.h"
+#include "base/command_line.h"
#include "content/browser/android/content_view_core_impl.h"
-#include "content/browser/android/media_resource_getter_impl.h"
+#include "content/browser/media/android/browser_demuxer_android.h"
+#include "content/browser/media/android/media_resource_getter_impl.h"
+#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/browser_context.h"
@@ -13,42 +16,75 @@
#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 "media/base/android/media_drm_bridge.h"
+#include "media/base/android/media_player_bridge.h"
+#include "media/base/android/media_source_player.h"
+#include "media/base/media_switches.h"
using media::MediaDrmBridge;
using media::MediaPlayerAndroid;
+using media::MediaPlayerBridge;
+using media::MediaPlayerManager;
+using media::MediaSourcePlayer;
// Threshold on the number of media players per renderer before we start
// attempting to release inactive media players.
static const int kMediaPlayerThreshold = 1;
-namespace media {
+namespace content {
-static MediaPlayerManager::FactoryFunction g_factory_function = NULL;
+static BrowserMediaPlayerManager::Factory g_factory = NULL;
// static
-CONTENT_EXPORT void MediaPlayerManager::RegisterFactoryFunction(
- FactoryFunction factory_function) {
- g_factory_function = factory_function;
+void BrowserMediaPlayerManager::RegisterFactory(Factory factory) {
+ g_factory = factory;
}
// static
-media::MediaPlayerManager* MediaPlayerManager::Create(
- content::RenderViewHost* render_view_host) {
- if (g_factory_function)
- return g_factory_function(render_view_host);
- return new content::BrowserMediaPlayerManager(render_view_host);
+BrowserMediaPlayerManager* BrowserMediaPlayerManager::Create(
+ RenderViewHost* rvh) {
+ if (g_factory)
+ return g_factory(rvh);
+ return new BrowserMediaPlayerManager(rvh);
}
-} // namespace media
+#if !defined(GOOGLE_TV)
+// static
+MediaPlayerAndroid* BrowserMediaPlayerManager::CreateMediaPlayer(
+ MediaPlayerHostMsg_Initialize_Type type,
+ int player_id,
+ const GURL& url,
+ const GURL& first_party_for_cookies,
+ int demuxer_client_id,
+ bool hide_url_log,
+ MediaPlayerManager* manager,
+ media::DemuxerAndroid* 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();
+ return media_player_bridge;
+ }
-namespace content {
+ case MEDIA_PLAYER_TYPE_MEDIA_SOURCE: {
+ return new MediaSourcePlayer(
+ player_id, manager, demuxer_client_id, demuxer);
+ }
+ }
+
+ NOTREACHED();
+ return NULL;
+}
+#endif
BrowserMediaPlayerManager::BrowserMediaPlayerManager(
RenderViewHost* render_view_host)
: RenderViewHostObserver(render_view_host),
fullscreen_player_id_(-1),
- web_contents_(WebContents::FromRenderViewHost(render_view_host)) {
+ web_contents_(WebContents::FromRenderViewHost(render_view_host)),
+ weak_ptr_factory_(this) {
}
BrowserMediaPlayerManager::~BrowserMediaPlayerManager() {}
@@ -67,14 +103,6 @@ bool BrowserMediaPlayerManager::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DestroyMediaPlayer, OnDestroyPlayer)
IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DestroyAllMediaPlayers,
DestroyAllMediaPlayers)
- IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DemuxerReady,
- OnDemuxerReady)
- IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_ReadFromDemuxerAck,
- OnReadFromDemuxerAck)
- IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DurationChanged,
- OnDurationChanged)
- IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaSeekRequestAck,
- OnMediaSeekRequestAck)
IPC_MESSAGE_HANDLER(MediaKeysHostMsg_InitializeCDM,
OnInitializeCDM)
IPC_MESSAGE_HANDLER(MediaKeysHostMsg_GenerateKeyRequest,
@@ -103,7 +131,7 @@ void BrowserMediaPlayerManager::FullscreenPlayerPlay() {
void BrowserMediaPlayerManager::FullscreenPlayerPause() {
MediaPlayerAndroid* player = GetFullscreenPlayer();
if (player) {
- player->Pause();
+ player->Pause(true);
Send(new MediaPlayerMsg_DidMediaPlayerPause(
routing_id(), fullscreen_player_id_));
}
@@ -194,11 +222,6 @@ void BrowserMediaPlayerManager::OnVideoSizeChanged(
video_view_->OnVideoSizeChanged(width, height);
}
-void BrowserMediaPlayerManager::OnReadFromDemuxer(
- int player_id, media::DemuxerStream::Type type) {
- Send(new MediaPlayerMsg_ReadFromDemuxer(routing_id(), player_id, type));
-}
-
void BrowserMediaPlayerManager::RequestMediaResources(int player_id) {
int num_active_player = 0;
ScopedVector<MediaPlayerAndroid>::iterator it;
@@ -269,22 +292,13 @@ MediaDrmBridge* BrowserMediaPlayerManager::GetDrmBridge(int media_keys_id) {
void BrowserMediaPlayerManager::DestroyAllMediaPlayers() {
players_.clear();
+ drm_bridges_.clear();
if (fullscreen_player_id_ != -1) {
video_view_.reset();
fullscreen_player_id_ = -1;
}
}
-void BrowserMediaPlayerManager::OnMediaSeekRequest(
- int player_id, base::TimeDelta time_to_seek, unsigned seek_request_id) {
- Send(new MediaPlayerMsg_MediaSeekRequest(
- routing_id(), player_id, time_to_seek, seek_request_id));
-}
-
-void BrowserMediaPlayerManager::OnMediaConfigRequest(int player_id) {
- Send(new MediaPlayerMsg_MediaConfigRequest(routing_id(), player_id));
-}
-
void BrowserMediaPlayerManager::OnProtectedSurfaceRequested(int player_id) {
if (fullscreen_player_id_ == player_id)
return;
@@ -376,16 +390,23 @@ void BrowserMediaPlayerManager::OnExitFullscreen(int player_id) {
}
void BrowserMediaPlayerManager::OnInitialize(
+ MediaPlayerHostMsg_Initialize_Type type,
int player_id,
const GURL& url,
- media::MediaPlayerAndroid::SourceType source_type,
- const GURL& first_party_for_cookies) {
+ const GURL& first_party_for_cookies,
+ int demuxer_client_id) {
+ DCHECK(type != MEDIA_PLAYER_TYPE_MEDIA_SOURCE || demuxer_client_id > 0)
+ << "Media source players must have positive demuxer client IDs: "
+ << demuxer_client_id;
+
RemovePlayer(player_id);
- RenderProcessHost* host = render_view_host()->GetProcess();
- AddPlayer(media::MediaPlayerAndroid::Create(
- player_id, url, source_type, first_party_for_cookies,
- host->GetBrowserContext()->IsOffTheRecord(), this));
+ RenderProcessHostImpl* host =
+ static_cast<RenderProcessHostImpl*>(render_view_host()->GetProcess());
+ AddPlayer(CreateMediaPlayer(
+ type, player_id, url, first_party_for_cookies, demuxer_client_id,
+ host->GetBrowserContext()->IsOffTheRecord(), this,
+ host->browser_demuxer_android()));
}
void BrowserMediaPlayerManager::OnStart(int player_id) {
@@ -400,10 +421,12 @@ void BrowserMediaPlayerManager::OnSeek(int player_id, base::TimeDelta time) {
player->SeekTo(time);
}
-void BrowserMediaPlayerManager::OnPause(int player_id) {
+void BrowserMediaPlayerManager::OnPause(
+ int player_id,
+ bool is_media_related_action) {
MediaPlayerAndroid* player = GetPlayer(player_id);
if (player)
- player->Pause();
+ player->Pause(is_media_related_action);
}
void BrowserMediaPlayerManager::OnSetVolume(int player_id, double volume) {
@@ -434,33 +457,11 @@ void BrowserMediaPlayerManager::OnDestroyPlayer(int player_id) {
fullscreen_player_id_ = -1;
}
-void BrowserMediaPlayerManager::OnDemuxerReady(
- int player_id,
- const media::MediaPlayerHostMsg_DemuxerReady_Params& params) {
- MediaPlayerAndroid* player = GetPlayer(player_id);
- if (player)
- player->DemuxerReady(params);
-}
-
-void BrowserMediaPlayerManager::OnReadFromDemuxerAck(
- int player_id,
- const media::MediaPlayerHostMsg_ReadFromDemuxerAck_Params& params) {
- MediaPlayerAndroid* player = GetPlayer(player_id);
- if (player)
- player->ReadFromDemuxerAck(params);
-}
-
-void BrowserMediaPlayerManager::OnMediaSeekRequestAck(
- int player_id, unsigned seek_request_id) {
- MediaPlayerAndroid* player = GetPlayer(player_id);
- if (player)
- player->OnSeekRequestAck(seek_request_id);
-}
-
void BrowserMediaPlayerManager::OnInitializeCDM(
int media_keys_id,
- const std::vector<uint8>& uuid) {
- AddDrmBridge(media_keys_id, uuid);
+ const std::vector<uint8>& uuid,
+ const GURL& frame_url) {
+ 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);
@@ -470,9 +471,29 @@ void BrowserMediaPlayerManager::OnGenerateKeyRequest(
int media_keys_id,
const std::string& type,
const std::vector<uint8>& init_data) {
+ if (CommandLine::ForCurrentProcess()
+ ->HasSwitch(switches::kDisableInfobarForProtectedMediaIdentifier)) {
+ GenerateKeyIfAllowed(media_keys_id, type, init_data, true);
+ return;
+ }
+
MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id);
- if (drm_bridge)
- drm_bridge->GenerateKeyRequest(type, &init_data[0], init_data.size());
+ if (!drm_bridge) {
+ DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found";
+ OnKeyError(media_keys_id, "", media::MediaKeys::kUnknownError, 0);
+ return;
+ }
+
+ WebContents* web_contents =
+ WebContents::FromRenderViewHost(render_view_host());
+ web_contents->GetDelegate()->RequestProtectedMediaIdentifierPermission(
+ web_contents,
+ drm_bridge->frame_url(),
+ base::Bind(&BrowserMediaPlayerManager::GenerateKeyIfAllowed,
+ weak_ptr_factory_.GetWeakPtr(),
+ media_keys_id,
+ type,
+ init_data));
}
void BrowserMediaPlayerManager::OnAddKey(int media_keys_id,
@@ -480,25 +501,33 @@ void BrowserMediaPlayerManager::OnAddKey(int media_keys_id,
const std::vector<uint8>& init_data,
const std::string& session_id) {
MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id);
- if (drm_bridge) {
- drm_bridge->AddKey(&key[0], key.size(), &init_data[0], init_data.size(),
- session_id);
+ if (!drm_bridge) {
+ DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found";
+ OnKeyError(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);
+ // 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|.
+ MediaPlayerAndroid* player = GetPlayer(media_keys_id);
+ if (player)
+ player->OnKeyAdded();
}
void BrowserMediaPlayerManager::OnCancelKeyRequest(
int media_keys_id,
const std::string& session_id) {
MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id);
- if (drm_bridge)
- drm_bridge->CancelKeyRequest(session_id);
-}
+ if (!drm_bridge) {
+ DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found";
+ OnKeyError(media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
+ return;
+ }
-void BrowserMediaPlayerManager::OnDurationChanged(
- int player_id, const base::TimeDelta& duration) {
- MediaPlayerAndroid* player = GetPlayer(player_id);
- if (player)
- player->DurationChanged(duration);
+ drm_bridge->CancelKeyRequest(session_id);
}
void BrowserMediaPlayerManager::AddPlayer(MediaPlayerAndroid* player) {
@@ -516,12 +545,40 @@ void BrowserMediaPlayerManager::RemovePlayer(int player_id) {
}
}
+scoped_ptr<media::MediaPlayerAndroid> BrowserMediaPlayerManager::SwapPlayer(
+ int player_id, media::MediaPlayerAndroid* player) {
+ media::MediaPlayerAndroid* previous_player = NULL;
+ for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin();
+ it != players_.end(); ++it) {
+ if ((*it)->player_id() == player_id) {
+ previous_player = *it;
+ players_.weak_erase(it);
+ players_.push_back(player);
+ break;
+ }
+ }
+ return scoped_ptr<media::MediaPlayerAndroid>(previous_player);
+}
+
void BrowserMediaPlayerManager::AddDrmBridge(int media_keys_id,
- const std::vector<uint8>& uuid) {
+ const std::vector<uint8>& uuid,
+ const GURL& frame_url) {
DCHECK(!GetDrmBridge(media_keys_id));
- scoped_ptr<MediaDrmBridge> drm_bridge(
- MediaDrmBridge::Create(media_keys_id, uuid, this));
- DCHECK(drm_bridge) << "failed to create drm bridge. ";
+ // TODO(xhwang/ddorwin): Pass the security level from key system.
+ std::string security_level = "L3";
+ if (CommandLine::ForCurrentProcess()
+ ->HasSwitch(switches::kMediaDrmEnableNonCompositing)) {
+ security_level = "L1";
+ }
+
+ scoped_ptr<MediaDrmBridge> drm_bridge(MediaDrmBridge::Create(
+ media_keys_id, uuid, frame_url, security_level, this));
+ if (!drm_bridge) {
+ DVLOG(1) << "failed to create drm bridge.";
+ OnKeyError(media_keys_id, "", media::MediaKeys::kUnknownError, 0);
+ return;
+ }
+
drm_bridges_.push_back(drm_bridge.release());
}
@@ -540,7 +597,7 @@ void BrowserMediaPlayerManager::OnSetMediaKeys(int player_id,
MediaPlayerAndroid* player = GetPlayer(player_id);
MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id);
if (!player || !drm_bridge) {
- NOTREACHED() << "OnSetMediaKeys(): Player and MediaKeys must be present.";
+ DVLOG(1) << "OnSetMediaKeys(): Player and MediaKeys must be present.";
return;
}
// TODO(qinmin): add the logic to decide whether we should create the
@@ -548,4 +605,22 @@ void BrowserMediaPlayerManager::OnSetMediaKeys(int player_id,
player->SetDrmBridge(drm_bridge);
}
+void BrowserMediaPlayerManager::GenerateKeyIfAllowed(
+ int media_keys_id,
+ const std::string& type,
+ const std::vector<uint8>& init_data,
+ bool allowed) {
+ if (!allowed)
+ 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);
+ return;
+ }
+
+ drm_bridge->GenerateKeyRequest(type, &init_data[0], init_data.size());
+}
+
} // namespace content
diff --git a/chromium/content/browser/android/browser_media_player_manager.h b/chromium/content/browser/media/android/browser_media_player_manager.h
index 7f193e96175..a26e1829cf8 100644
--- a/chromium/content/browser/android/browser_media_player_manager.h
+++ b/chromium/content/browser/media/android/browser_media_player_manager.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_ANDROID_BROWSER_MEDIA_PLAYER_MANAGER_H_
-#define CONTENT_BROWSER_ANDROID_BROWSER_MEDIA_PLAYER_MANAGER_H_
+#ifndef CONTENT_BROWSER_MEDIA_ANDROID_BROWSER_MEDIA_PLAYER_MANAGER_H_
+#define CONTENT_BROWSER_MEDIA_ANDROID_BROWSER_MEDIA_PLAYER_MANAGER_H_
#include <map>
#include <string>
@@ -15,14 +15,15 @@
#include "base/memory/scoped_vector.h"
#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 "media/base/android/demuxer_stream_player_params.h"
#include "media/base/android/media_player_android.h"
#include "media/base/android/media_player_manager.h"
#include "ui/gfx/rect_f.h"
#include "url/gurl.h"
namespace media {
+class DemuxerAndroid;
class MediaDrmBridge;
}
@@ -39,6 +40,13 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
: public RenderViewHostObserver,
public media::MediaPlayerManager {
public:
+ // Permits embedders to provide an extended version of the class.
+ typedef BrowserMediaPlayerManager* (*Factory)(RenderViewHost*);
+ static void RegisterFactory(Factory factory);
+
+ // Returns a new instance using the registered factory if available.
+ static BrowserMediaPlayerManager* Create(RenderViewHost* rvh);
+
virtual ~BrowserMediaPlayerManager();
// RenderViewHostObserver overrides.
@@ -68,8 +76,6 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
virtual void OnError(int player_id, int error) OVERRIDE;
virtual void OnVideoSizeChanged(
int player_id, int width, int height) OVERRIDE;
- virtual void OnReadFromDemuxer(int player_id,
- media::DemuxerStream::Type type) OVERRIDE;
virtual void RequestMediaResources(int player_id) OVERRIDE;
virtual void ReleaseMediaResources(int player_id) OVERRIDE;
virtual media::MediaResourceGetter* GetMediaResourceGetter() OVERRIDE;
@@ -77,9 +83,6 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
virtual media::MediaPlayerAndroid* GetPlayer(int player_id) OVERRIDE;
virtual media::MediaDrmBridge* GetDrmBridge(int media_keys_id) OVERRIDE;
virtual void DestroyAllMediaPlayers() OVERRIDE;
- virtual void OnMediaSeekRequest(int player_id, base::TimeDelta time_to_seek,
- unsigned seek_request_id) OVERRIDE;
- virtual void OnMediaConfigRequest(int player_id) OVERRIDE;
virtual void OnProtectedSurfaceRequested(int player_id) OVERRIDE;
virtual void OnKeyAdded(int media_keys_id,
const std::string& session_id) OVERRIDE;
@@ -98,35 +101,27 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
#endif
protected:
- friend MediaPlayerManager* MediaPlayerManager::Create(
- content::RenderViewHost*);
-
- // The instance of this class is supposed to be created by either Create()
- // method of MediaPlayerManager or the derived classes constructors.
+ // Clients must use Create() or subclass constructor.
explicit BrowserMediaPlayerManager(RenderViewHost* render_view_host);
// Message handlers.
virtual void OnEnterFullscreen(int player_id);
virtual void OnExitFullscreen(int player_id);
virtual void OnInitialize(
+ MediaPlayerHostMsg_Initialize_Type type,
int player_id,
const GURL& url,
- media::MediaPlayerAndroid::SourceType source_type,
- const GURL& first_party_for_cookies);
+ 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 OnPause(int player_id);
+ 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);
virtual void OnDestroyPlayer(int player_id);
- virtual void OnDemuxerReady(
- int player_id,
- const media::MediaPlayerHostMsg_DemuxerReady_Params& params);
- virtual void OnReadFromDemuxerAck(
- int player_id,
- const media::MediaPlayerHostMsg_ReadFromDemuxerAck_Params& params);
- void OnMediaSeekRequestAck(int player_id, unsigned seek_request_id);
- void OnInitializeCDM(int media_keys_id, const std::vector<uint8>& uuid);
+ 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);
@@ -135,7 +130,6 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
const std::vector<uint8>& init_data,
const std::string& session_id);
void OnCancelKeyRequest(int media_keys_id, const std::string& session_id);
- void OnDurationChanged(int player_id, const base::TimeDelta& duration);
void OnSetMediaKeys(int player_id, int media_keys_id);
#if defined(GOOGLE_TV)
@@ -149,13 +143,45 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
// Removes the player with the specified id.
void RemovePlayer(int player_id);
- // Add a new MediaDrmBridge for the given |uuid| and |media_keys_id|.
- void AddDrmBridge(int media_keys_id, const std::vector<uint8>& uuid);
+ // Replaces a player with the specified id with a given MediaPlayerAndroid
+ // object. This will also return the original MediaPlayerAndroid object that
+ // was replaced.
+ scoped_ptr<media::MediaPlayerAndroid> SwapPlayer(
+ int player_id,
+ media::MediaPlayerAndroid* player);
+
+ // Add a new MediaDrmBridge for the given |uuid|, |media_keys_id|, and
+ // |frame_url|.
+ void AddDrmBridge(int media_keys_id,
+ const std::vector<uint8>& uuid,
+ const GURL& frame_url);
// Removes the DRM bridge with the specified id.
void RemoveDrmBridge(int media_keys_id);
private:
+ void GenerateKeyIfAllowed(int media_keys_id,
+ const std::string& type,
+ const std::vector<uint8>& init_data,
+ bool allowed);
+
+ // Constructs a MediaPlayerAndroid object. Declared static to permit embedders
+ // to override functionality.
+ //
+ // Objects must call |manager->RequestMediaResources()| before decoding
+ // and |manager->ReleaseMediaSources()| after finishing. This allows the
+ // manager to track decoding resources across the process and free them as
+ // needed.
+ static media::MediaPlayerAndroid* CreateMediaPlayer(
+ MediaPlayerHostMsg_Initialize_Type type,
+ int player_id,
+ const GURL& url,
+ const GURL& first_party_for_cookies,
+ int demuxer_client_id,
+ bool hide_url_log,
+ media::MediaPlayerManager* manager,
+ media::DemuxerAndroid* demuxer);
+
// An array of managed players.
ScopedVector<media::MediaPlayerAndroid> players_;
@@ -174,9 +200,11 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
// Object for retrieving resources media players.
scoped_ptr<media::MediaResourceGetter> media_resource_getter_;
+ base::WeakPtrFactory<BrowserMediaPlayerManager> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(BrowserMediaPlayerManager);
};
} // namespace content
-#endif // CONTENT_BROWSER_ANDROID_BROWSER_MEDIA_PLAYER_MANAGER_H_
+#endif // CONTENT_BROWSER_MEDIA_ANDROID_BROWSER_MEDIA_PLAYER_MANAGER_H_
diff --git a/chromium/content/browser/media/android/media_drm_credential_manager.cc b/chromium/content/browser/media/android/media_drm_credential_manager.cc
new file mode 100644
index 00000000000..8151256dad6
--- /dev/null
+++ b/chromium/content/browser/media/android/media_drm_credential_manager.cc
@@ -0,0 +1,109 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/android/media_drm_credential_manager.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "jni/MediaDrmCredentialManager_jni.h"
+#include "media/base/android/media_drm_bridge.h"
+#include "url/gurl.h"
+
+using base::android::ScopedJavaGlobalRef;
+
+namespace {
+
+void MediaDrmCredentialManagerCallback(
+ const ScopedJavaGlobalRef<jobject>& j_media_drm_credential_manager_callback,
+ bool succeeded) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ content::Java_MediaDrmCredentialManagerCallback_onCredentialResetFinished(
+ env, j_media_drm_credential_manager_callback.obj(), succeeded);
+}
+
+} // namespace
+
+namespace content {
+
+// TODO(qinmin): Move the UUID definition to some common places.
+static const uint8 kWidevineUuid[16] = {
+ 0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE,
+ 0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED };
+
+MediaDrmCredentialManager::MediaDrmCredentialManager() {};
+
+MediaDrmCredentialManager::~MediaDrmCredentialManager() {};
+
+// static
+MediaDrmCredentialManager* MediaDrmCredentialManager::GetInstance() {
+ return Singleton<MediaDrmCredentialManager>::get();
+}
+
+void MediaDrmCredentialManager::ResetCredentials(
+ const ResetCredentialsCB& callback) {
+ // Ignore reset request if one is already in progress.
+ if (!reset_credentials_cb_.is_null())
+ return;
+
+ reset_credentials_cb_ = callback;
+
+ // First reset the L3 credential.
+ if (!ResetCredentialsInternal("L3")) {
+ // TODO(qinmin): We should post a task instead.
+ base::ResetAndReturn(&reset_credentials_cb_).Run(false);
+ }
+}
+
+// static
+void ResetCredentials(
+ JNIEnv* env,
+ jclass clazz,
+ jobject j_media_drm_credential_manager_callback) {
+ MediaDrmCredentialManager* media_drm_credential_manager =
+ MediaDrmCredentialManager::GetInstance();
+
+ ScopedJavaGlobalRef<jobject> j_scoped_media_drm_credential_manager_callback;
+ j_scoped_media_drm_credential_manager_callback.Reset(
+ env, j_media_drm_credential_manager_callback);
+
+ MediaDrmCredentialManager::ResetCredentialsCB callback_runner =
+ base::Bind(&MediaDrmCredentialManagerCallback,
+ j_scoped_media_drm_credential_manager_callback);
+
+ media_drm_credential_manager->ResetCredentials(callback_runner);
+}
+
+void MediaDrmCredentialManager::OnResetCredentialsCompleted(
+ const std::string& security_level, bool success) {
+ if (security_level == "L3" && success) {
+ if (ResetCredentialsInternal("L1"))
+ return;
+ success = false;
+ }
+
+ base::ResetAndReturn(&reset_credentials_cb_).Run(success);
+ media_drm_bridge_.reset();
+}
+
+bool MediaDrmCredentialManager::ResetCredentialsInternal(
+ const std::string& security_level) {
+ std::vector<uint8> uuid(kWidevineUuid, kWidevineUuid + 16);
+ media_drm_bridge_ = media::MediaDrmBridge::Create(
+ 0, uuid, GURL(), security_level, NULL);
+ if (!media_drm_bridge_)
+ return false;
+ media_drm_bridge_->ResetDeviceCredentials(
+ base::Bind(&MediaDrmCredentialManager::OnResetCredentialsCompleted,
+ base::Unretained(this), security_level));
+ return true;
+}
+
+// static
+bool MediaDrmCredentialManager::RegisterMediaDrmCredentialManager(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/android/media_drm_credential_manager.h b/chromium/content/browser/media/android/media_drm_credential_manager.h
new file mode 100644
index 00000000000..6b6845e2b80
--- /dev/null
+++ b/chromium/content/browser/media/android/media_drm_credential_manager.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_BROWSER_MEDIA_ANDROID_MEDIA_DRM_CREDENTIAL_MANAGER_H_
+#define CONTENT_BROWSER_MEDIA_ANDROID_MEDIA_DRM_CREDENTIAL_MANAGER_H_
+
+#include <jni.h>
+#include <string>
+
+#include "base/callback.h"
+#include "base/memory/singleton.h"
+#include "media/base/android/media_drm_bridge.h"
+
+namespace content {
+
+// This class manages the media DRM credentials on Android.
+class MediaDrmCredentialManager {
+ public:
+ static MediaDrmCredentialManager* GetInstance();
+
+ typedef base::Callback<void(bool)> ResetCredentialsCB;
+
+ // Called to reset the DRM credentials. (for Java)
+ static void ResetCredentials(JNIEnv* env, jclass clazz, jobject callback);
+
+ // Called to reset the DRM credentials.
+ void ResetCredentials(const ResetCredentialsCB& callback);
+
+ static bool RegisterMediaDrmCredentialManager(JNIEnv* env);
+
+ private:
+ friend struct DefaultSingletonTraits<MediaDrmCredentialManager>;
+ friend class Singleton<MediaDrmCredentialManager>;
+
+ MediaDrmCredentialManager();
+ ~MediaDrmCredentialManager();
+
+
+ // Callback function passed to MediaDrmBridge. It is called when reset
+ // completed.
+ void OnResetCredentialsCompleted(const std::string& security_level,
+ bool success);
+
+ // Reset DRM credentials for a particular security level. Returns false if
+ // we fail to create the MediaDrmBridge, or true otherwise.
+ bool ResetCredentialsInternal(const std::string& security_level);
+
+ // The MediaDrmBridge object used to perform the credential reset.
+ scoped_ptr<media::MediaDrmBridge> media_drm_bridge_;
+
+ // The callback provided by the caller.
+ ResetCredentialsCB reset_credentials_cb_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaDrmCredentialManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_ANDROID_MEDIA_DRM_CREDENTIAL_MANAGER_H_
diff --git a/chromium/content/browser/android/media_resource_getter_impl.cc b/chromium/content/browser/media/android/media_resource_getter_impl.cc
index 49703101b24..53a5094dce4 100644
--- a/chromium/content/browser/android/media_resource_getter_impl.cc
+++ b/chromium/content/browser/media/android/media_resource_getter_impl.cc
@@ -1,8 +1,8 @@
-// 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/android/media_resource_getter_impl.h"
+#include "content/browser/media/android/media_resource_getter_impl.h"
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
diff --git a/chromium/content/browser/android/media_resource_getter_impl.h b/chromium/content/browser/media/android/media_resource_getter_impl.h
index 1d152447e7c..2b6e42ea313 100644
--- a/chromium/content/browser/android/media_resource_getter_impl.h
+++ b/chromium/content/browser/media/android/media_resource_getter_impl.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_ANDROID_MEDIA_RESOURCE_GETTER_IMPL_H_
-#define CONTENT_BROWSER_ANDROID_MEDIA_RESOURCE_GETTER_IMPL_H_
+#ifndef CONTENT_BROWSER_MEDIA_ANDROID_MEDIA_RESOURCE_GETTER_IMPL_H_
+#define CONTENT_BROWSER_MEDIA_ANDROID_MEDIA_RESOURCE_GETTER_IMPL_H_
#include <jni.h>
#include <string>
@@ -82,4 +82,4 @@ class MediaResourceGetterImpl : public media::MediaResourceGetter {
} // namespace content
-#endif // CONTENT_BROWSER_ANDROID_MEDIA_RESOURCE_GETTER_IMPL_H_
+#endif // CONTENT_BROWSER_MEDIA_ANDROID_MEDIA_RESOURCE_GETTER_IMPL_H_
diff --git a/chromium/content/browser/media/encrypted_media_browsertest.cc b/chromium/content/browser/media/encrypted_media_browsertest.cc
index ce5dc4e6ba0..b3df24d643b 100644
--- a/chromium/content/browser/media/encrypted_media_browsertest.cc
+++ b/chromium/content/browser/media/encrypted_media_browsertest.cc
@@ -9,30 +9,10 @@
#include "content/browser/media/media_browsertest.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
-#include "content/shell/shell.h"
-
-#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
-
-#if defined(WIDEVINE_CDM_AVAILABLE) && defined(OS_LINUX)
-#include <gnu/libc-version.h>
-#endif // defined(WIDEVINE_CDM_AVAILABLE) && defined(OS_LINUX)
-
-#if defined(ENABLE_PEPPER_CDMS)
-// Platform-specific filename relative to the chrome executable.
-static const char kClearKeyCdmAdapterFileName[] =
-#if defined(OS_MACOSX)
- "clearkeycdmadapter.plugin";
-#elif defined(OS_WIN)
- "clearkeycdmadapter.dll";
-#elif defined(OS_POSIX)
- "libclearkeycdmadapter.so";
-#endif
-#endif // defined(ENABLE_PEPPER_CDMS)
+#include "content/shell/browser/shell.h"
// Available key systems.
static const char kClearKeyKeySystem[] = "webkit-org.w3.clearkey";
-static const char kExternalClearKeyKeySystem[] =
- "org.chromium.externalclearkey";
// Supported media types.
static const char kWebMAudioOnly[] = "audio/webm; codecs=\"vorbis\"";
@@ -41,8 +21,9 @@ 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\"";
-// Common test expectations.
-static const char kKeyError[] = "KEYERROR";
+// EME-specific test results and errors.
+static const char kEmeGkrException[] = "GENERATE_KEY_REQUEST_EXCEPTION";
+static const char kEmeKeyError[] = "KEYERROR";
// The type of video src used to load media.
enum SrcType {
@@ -105,109 +86,25 @@ class EncryptedMediaTest : public content::MediaBrowserTest,
}
protected:
-#if defined(ENABLE_PEPPER_CDMS)
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
- RegisterPepperCdm(command_line, kClearKeyCdmAdapterFileName,
- kExternalClearKeyKeySystem);
- }
-
- virtual void RegisterPepperCdm(CommandLine* command_line,
- const std::string& adapter_name,
- const std::string& key_system) {
- // Append the switch to register the Clear Key CDM Adapter.
- base::FilePath plugin_dir;
- EXPECT_TRUE(PathService::Get(base::DIR_MODULE, &plugin_dir));
- base::FilePath plugin_lib = plugin_dir.AppendASCII(adapter_name);
- EXPECT_TRUE(base::PathExists(plugin_lib));
- base::FilePath::StringType pepper_plugin = plugin_lib.value();
- pepper_plugin.append(FILE_PATH_LITERAL("#CDM#0.1.0.0;"));
-#if defined(OS_WIN)
- pepper_plugin.append(ASCIIToWide(GetPepperType(key_system)));
-#else
- pepper_plugin.append(GetPepperType(key_system));
-#endif
- command_line->AppendSwitchNative(switches::kRegisterPepperPlugins,
- pepper_plugin);
- }
-
- // Adapted from key_systems.cc.
- std::string GetPepperType(const std::string& key_system) {
- if (key_system == kExternalClearKeyKeySystem)
- return "application/x-ppapi-clearkey-cdm";
-#if defined(WIDEVINE_CDM_AVAILABLE)
- if (key_system == kWidevineKeySystem)
- return "application/x-ppapi-widevine-cdm";
-#endif // WIDEVINE_CDM_AVAILABLE
-
- NOTREACHED();
- return "";
+ // 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(kEmeKeyError));
}
-#endif // defined(ENABLE_PEPPER_CDMS)
};
-#if defined(WIDEVINE_CDM_AVAILABLE)
-class WVEncryptedMediaTest : public EncryptedMediaTest {
- public:
- // Tests that the following happen after trying to play encrypted media:
- // - webkitneedkey event is fired.
- // - webkitGenerateKeyRequest() does not fail.
- // - webkitkeymessage is fired
- // - webkitAddKey() generates a WebKitKeyError since no real WV key is added.
- void TestMSESimplePlayback(const char* encrypted_media,
- const char* media_type, const char* key_system) {
- // TODO(shadi): Remove after bots upgrade to precise.
- // Don't run on lucid bots since the CDM is not compatible (glibc < 2.14)
-#if defined(OS_LINUX)
- if (strcmp(gnu_get_libc_version(), "2.11.1") == 0) {
- LOG(INFO) << "Skipping test; not supported on glibc version: "
- << gnu_get_libc_version();
- return;
- }
-#endif // defined(OS_LINUX)
- EncryptedMediaTest::TestMSESimplePlayback(encrypted_media, media_type,
- key_system, kKeyError);
- bool receivedKeyMessage = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
- "window.domAutomationController.send(video.receivedKeyMessage);",
- &receivedKeyMessage));
- ASSERT_TRUE(receivedKeyMessage);
- }
-
- protected:
-#if defined(ENABLE_PEPPER_CDMS)
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
- RegisterPepperCdm(command_line, kWidevineCdmAdapterFileName,
- kWidevineKeySystem);
- }
-#endif // defined(ENABLE_PEPPER_CDMS)
-};
-#endif // defined(WIDEVINE_CDM_AVAILABLE)
-
INSTANTIATE_TEST_CASE_P(ClearKey, EncryptedMediaTest,
::testing::Combine(
::testing::Values(kClearKeyKeySystem), ::testing::Values(SRC, MSE)));
-// External Clear Key is currently only used on platforms that use Pepper CDMs.
-#if defined(ENABLE_PEPPER_CDMS)
-INSTANTIATE_TEST_CASE_P(ExternalClearKey, EncryptedMediaTest,
- ::testing::Combine(
- ::testing::Values(kExternalClearKeyKeySystem),
- ::testing::Values(SRC, MSE)));
-
-IN_PROC_BROWSER_TEST_F(EncryptedMediaTest, ConfigChangeVideo_ExternalClearKey) {
- TestConfigChange(kExternalClearKeyKeySystem, kEnded);
-}
-#endif // defined(ENABLE_PEPPER_CDMS)
-
IN_PROC_BROWSER_TEST_F(EncryptedMediaTest, ConfigChangeVideo_ClearKey) {
TestConfigChange(kClearKeyKeySystem, kEnded);
}
IN_PROC_BROWSER_TEST_F(EncryptedMediaTest, InvalidKeySystem) {
TestMSESimplePlayback("bear-320x240-av-enc_av.webm", kWebMAudioVideo,
- "com.example.invalid",
- "GENERATE_KEY_REQUEST_EXCEPTION");
+ "com.example.invalid", kEmeGkrException);
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_WebM) {
@@ -243,68 +140,11 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, FrameChangeVideo) {
TestFrameSizeChange(GetParam(), kEnded);
}
-#if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS)
-IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_MP4) {
- std::tr1::tuple<const char*, SrcType> test_params = GetParam();
- // MP4 without MSE is not support yet, http://crbug.com/170793.
- if (std::tr1::get<1>(test_params) != MSE) {
- LOG(INFO) << "Skipping test; Can only play MP4 encrypted streams by MSE.";
- return;
- }
- TestMSESimplePlayback("bear-640x360-v_frag-cenc.mp4", kMP4VideoOnly,
- std::tr1::get<0>(test_params), kEnded);
-}
-
-IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_MP4) {
- std::tr1::tuple<const char*, SrcType> test_params = GetParam();
- // MP4 without MSE is not support yet, http://crbug.com/170793.
- if (std::tr1::get<1>(test_params) != MSE) {
- LOG(INFO) << "Skipping test; Can only play MP4 encrypted streams by MSE.";
- return;
- }
- TestMSESimplePlayback("bear-640x360-a_frag-cenc.mp4", kMP4AudioOnly,
- std::tr1::get<0>(test_params), kEnded);
-}
-#endif
-
-// Run only when WV CDM is available.
-#if defined(WIDEVINE_CDM_AVAILABLE)
-IN_PROC_BROWSER_TEST_F(WVEncryptedMediaTest, Playback_AudioOnly_WebM) {
- TestMSESimplePlayback("bear-a-enc_a.webm", kWebMAudioOnly,
- kWidevineKeySystem);
-}
-
-IN_PROC_BROWSER_TEST_F(WVEncryptedMediaTest, Playback_AudioClearVideo_WebM) {
- TestMSESimplePlayback("bear-320x240-av-enc_a.webm", kWebMAudioVideo,
- kWidevineKeySystem);
-}
-
-IN_PROC_BROWSER_TEST_F(WVEncryptedMediaTest, Playback_VideoAudio_WebM) {
- TestMSESimplePlayback("bear-320x240-av-enc_av.webm", kWebMAudioVideo,
- kWidevineKeySystem);
-}
-
-IN_PROC_BROWSER_TEST_F(WVEncryptedMediaTest, Playback_VideoOnly_WebM) {
- TestMSESimplePlayback("bear-320x240-v-enc_v.webm", kWebMVideoOnly,
- kWidevineKeySystem);
-}
-
-IN_PROC_BROWSER_TEST_F(WVEncryptedMediaTest, Playback_VideoClearAudio_WebM) {
- TestMSESimplePlayback("bear-320x240-av-enc_v.webm", kWebMAudioVideo,
- kWidevineKeySystem);
-}
-
-#if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS)
-IN_PROC_BROWSER_TEST_F(WVEncryptedMediaTest, Playback_VideoOnly_MP4) {
- TestMSESimplePlayback("bear-640x360-v_frag-cenc.mp4", kMP4VideoOnly,
- kWidevineKeySystem);
-}
-
-IN_PROC_BROWSER_TEST_F(WVEncryptedMediaTest, Playback_AudioOnly_MP4) {
- TestMSESimplePlayback("bear-640x360-a_frag-cenc.mp4", kMP4AudioOnly,
- kWidevineKeySystem);
+// 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);
}
-#endif // defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS)
-#endif // defined(WIDEVINE_CDM_AVAILABLE)
} // namespace content
diff --git a/chromium/content/browser/media/media_browsertest.cc b/chromium/content/browser/media/media_browsertest.cc
index 1d830354c9e..c264ec949fc 100644
--- a/chromium/content/browser/media/media_browsertest.cc
+++ b/chromium/content/browser/media/media_browsertest.cc
@@ -9,7 +9,7 @@
#include "content/public/browser/web_contents.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test_utils.h"
-#include "content/shell/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test_utils.h"
// TODO(wolenetz): Fix Media.YUV* tests on MSVS 2012 x64. crbug.com/180074
@@ -59,16 +59,20 @@ void MediaBrowserTest::RunMediaTestPage(
}
void MediaBrowserTest::RunTest(const GURL& gurl, const char* expected) {
- const string16 kExpected = ASCIIToUTF16(expected);
+ const string16 expected_title = ASCIIToUTF16(expected);
DVLOG(1) << "Running test URL: " << gurl;
- TitleWatcher title_watcher(shell()->web_contents(), kExpected);
- title_watcher.AlsoWaitForTitle(ASCIIToUTF16(kEnded));
- title_watcher.AlsoWaitForTitle(ASCIIToUTF16(kError));
- title_watcher.AlsoWaitForTitle(ASCIIToUTF16(kFailed));
+ TitleWatcher title_watcher(shell()->web_contents(), expected_title);
+ AddWaitForTitles(&title_watcher);
NavigateToURL(shell(), gurl);
string16 final_title = title_watcher.WaitAndGetTitle();
- EXPECT_EQ(kExpected, final_title);
+ EXPECT_EQ(expected_title, final_title);
+}
+
+void MediaBrowserTest::AddWaitForTitles(content::TitleWatcher* title_watcher) {
+ title_watcher->AlsoWaitForTitle(ASCIIToUTF16(kEnded));
+ title_watcher->AlsoWaitForTitle(ASCIIToUTF16(kError));
+ title_watcher->AlsoWaitForTitle(ASCIIToUTF16(kFailed));
}
// Tests playback and seeking of an audio or video file over file or http based
@@ -117,7 +121,7 @@ IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearSilentWebm) {
PlayVideo("bear_silent.webm", GetParam());
}
-#if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS)
+#if defined(USE_PROPRIETARY_CODECS)
IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearMp4) {
PlayVideo("bear.mp4", GetParam());
}
@@ -139,7 +143,7 @@ IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearMovPcmS24be) {
#endif
#if defined(OS_CHROMEOS)
-#if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS)
+#if defined(USE_PROPRIETARY_CODECS)
IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearAviMp3Mpeg4) {
PlayVideo("bear_mpeg4_mp3.avi", GetParam());
}
@@ -217,7 +221,7 @@ IN_PROC_BROWSER_TEST_F(MediaTest, MAYBE(Yuv420pVp8)) {
RunColorFormatTest("yuv420p.webm", "ENDED");
}
-#if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS)
+#if defined(USE_PROPRIETARY_CODECS)
IN_PROC_BROWSER_TEST_F(MediaTest, MAYBE(Yuv420pH264)) {
RunColorFormatTest("yuv420p.mp4", "ENDED");
}
@@ -239,7 +243,7 @@ IN_PROC_BROWSER_TEST_F(MediaTest, MAYBE(Yuv444pH264)) {
IN_PROC_BROWSER_TEST_F(MediaTest, Yuv420pMpeg4) {
RunColorFormatTest("yuv420p.avi", "ENDED");
}
-#endif
-#endif
+#endif // defined(OS_CHROMEOS)
+#endif // defined(USE_PROPRIETARY_CODECS)
} // namespace content
diff --git a/chromium/content/browser/media/media_browsertest.h b/chromium/content/browser/media/media_browsertest.h
index 013283b1ed6..6637ead2706 100644
--- a/chromium/content/browser/media/media_browsertest.h
+++ b/chromium/content/browser/media/media_browsertest.h
@@ -2,21 +2,30 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#ifndef CONTENT_BROWSER_MEDIA_MEDIA_BROWSERTEST_H_
+#define CONTENT_BROWSER_MEDIA_MEDIA_BROWSERTEST_H_
+
+#include <utility>
+#include <vector>
+
#include "content/test/content_browser_test.h"
namespace content {
+class TitleWatcher;
+
// Class used to automate running media related browser tests. The functions
// assume that media files are located under files/media/ folder known to
// the test http server.
class MediaBrowserTest : public ContentBrowserTest {
public:
+ typedef std::pair<const char*, const char*> StringPair;
+
+ // Common test results.
static const char kEnded[];
static const char kError[];
static const char kFailed[];
- typedef std::pair<const char*, const char*> StringPair;
-
virtual void SetUp() OVERRIDE;
// Runs a html page with a list of URL query parameters.
@@ -30,6 +39,10 @@ class MediaBrowserTest : public ContentBrowserTest {
// Opens a URL and waits for the document title to match either one of the
// default strings or the expected string.
void RunTest(const GURL& gurl, const char* expected);
+
+ virtual void AddWaitForTitles(content::TitleWatcher* title_watcher);
};
} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_MEDIA_BROWSERTEST_H_
diff --git a/chromium/content/browser/media/media_internals.cc b/chromium/content/browser/media/media_internals.cc
index 273eeaeaf9f..22f164ddccc 100644
--- a/chromium/content/browser/media/media_internals.cc
+++ b/chromium/content/browser/media/media_internals.cc
@@ -9,6 +9,7 @@
#include "base/strings/stringprintf.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_ui.h"
+#include "media/audio/audio_parameters.h"
#include "media/base/media_log.h"
#include "media/base/media_log_event.h"
@@ -20,11 +21,15 @@ MediaInternals* MediaInternals::GetInstance() {
MediaInternals::~MediaInternals() {}
+namespace {
+std::string FormatAudioStreamName(void* host, int stream_id) {
+ return base::StringPrintf("audio_streams.%p:%d", host, stream_id);
+}
+}
+
void MediaInternals::OnDeleteAudioStream(void* host, int stream_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- std::string stream = base::StringPrintf("audio_streams.%p:%d",
- host, stream_id);
- DeleteItem(stream);
+ DeleteItem(FormatAudioStreamName(host, stream_id));
}
void MediaInternals::OnSetAudioStreamPlaying(
@@ -34,8 +39,55 @@ void MediaInternals::OnSetAudioStreamPlaying(
"playing", new base::FundamentalValue(playing));
}
-void MediaInternals::OnSetAudioStreamStatus(
- void* host, int stream_id, const std::string& status) {
+void MediaInternals::OnAudioStreamCreated(void* host,
+ int stream_id,
+ const media::AudioParameters& params,
+ const std::string& input_device_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ StoreAudioStream(host,
+ stream_id,
+ "input_device_id",
+ Value::CreateStringValue(input_device_id));
+
+ StoreAudioStream(
+ host, stream_id, "status", Value::CreateStringValue("created"));
+
+ StoreAudioStream(
+ host, stream_id, "stream_id", Value::CreateIntegerValue(stream_id));
+
+ StoreAudioStream(host,
+ stream_id,
+ "input_channels",
+ Value::CreateIntegerValue(params.input_channels()));
+
+ StoreAudioStream(host,
+ stream_id,
+ "frames_per_buffer",
+ Value::CreateIntegerValue(params.frames_per_buffer()));
+
+ StoreAudioStream(host,
+ stream_id,
+ "sample_rate",
+ Value::CreateIntegerValue(params.sample_rate()));
+
+ StoreAudioStream(host,
+ stream_id,
+ "output_channels",
+ Value::CreateIntegerValue(params.channels()));
+
+ StoreAudioStream(
+ host,
+ stream_id,
+ "channel_layout",
+ Value::CreateStringValue(ChannelLayoutToString(params.channel_layout())));
+
+ SendEverything();
+}
+
+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));
@@ -92,13 +144,21 @@ void MediaInternals::SendEverything() {
MediaInternals::MediaInternals() {
}
+void MediaInternals::StoreAudioStream(void* host,
+ int stream_id,
+ const std::string& property,
+ base::Value* value) {
+ StoreItem(FormatAudioStreamName(host, stream_id), property, value);
+}
+
void MediaInternals::UpdateAudioStream(void* host,
int stream_id,
const std::string& property,
base::Value* value) {
- std::string stream = base::StringPrintf("audio_streams.%p:%d",
- host, stream_id);
- UpdateItem("media.addAudioStream", stream, property, value);
+ UpdateItem("media.updateAudioStream",
+ FormatAudioStreamName(host, stream_id),
+ property,
+ value);
}
void MediaInternals::DeleteItem(const std::string& item) {
@@ -107,9 +167,9 @@ void MediaInternals::DeleteItem(const std::string& item) {
SendUpdate("media.onItemDeleted", value.get());
}
-void MediaInternals::UpdateItem(
- const std::string& update_fn, const std::string& id,
- const std::string& property, base::Value* 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();
@@ -117,6 +177,14 @@ void MediaInternals::UpdateItem(
item_properties->SetString("id", id);
}
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);
}
diff --git a/chromium/content/browser/media/media_internals.h b/chromium/content/browser/media/media_internals.h
index 4a4d2efc7d1..24b314ef321 100644
--- a/chromium/content/browser/media/media_internals.h
+++ b/chromium/content/browser/media/media_internals.h
@@ -16,6 +16,7 @@
#include "content/public/common/media_stream_request.h"
namespace media {
+class AudioParameters;
struct MediaLogEvent;
}
@@ -36,8 +37,14 @@ class CONTENT_EXPORT MediaInternals {
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);
+ 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".
@@ -73,9 +80,21 @@ class CONTENT_EXPORT MediaInternals {
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,
diff --git a/chromium/content/browser/media/media_internals_handler.cc b/chromium/content/browser/media/media_internals_handler.cc
index 1ea6b04c663..1715330e8e5 100644
--- a/chromium/content/browser/media/media_internals_handler.cc
+++ b/chromium/content/browser/media/media_internals_handler.cc
@@ -7,7 +7,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/values.h"
-#include "content/browser//media/media_internals_proxy.h"
+#include "content/browser/media/media_internals_proxy.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
diff --git a/chromium/content/browser/media/media_internals_ui.cc b/chromium/content/browser/media/media_internals_ui.cc
index 83638148bf9..f185bdca23e 100644
--- a/chromium/content/browser/media/media_internals_ui.cc
+++ b/chromium/content/browser/media/media_internals_ui.cc
@@ -21,12 +21,6 @@ WebUIDataSource* CreateMediaInternalsHTMLSource() {
WebUIDataSource::Create(kChromeUIMediaInternalsHost);
source->SetJsonPath("strings.js");
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableNewMediaInternals)) {
- source->AddResourcePath("media_internals.js", IDR_MEDIA_INTERNALS_NEW_JS);
- source->SetDefaultResource(IDR_MEDIA_INTERNALS_NEW_HTML);
- return source;
- }
source->AddResourcePath("media_internals.js", IDR_MEDIA_INTERNALS_JS);
source->SetDefaultResource(IDR_MEDIA_INTERNALS_HTML);
diff --git a/chromium/content/browser/media/media_internals_unittest.cc b/chromium/content/browser/media/media_internals_unittest.cc
index 58c8f91dc68..173ba36539f 100644
--- a/chromium/content/browser/media/media_internals_unittest.cc
+++ b/chromium/content/browser/media/media_internals_unittest.cc
@@ -7,7 +7,10 @@
#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 "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"
@@ -58,6 +61,46 @@ class MediaInternalsTest : public testing::Test {
scoped_ptr<MediaInternals> internals_;
};
+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_F(MediaInternalsTest, UpdateAddsNewItem) {
UpdateItem("some.item", "testing", new base::FundamentalValue(true));
bool testing = false;
diff --git a/chromium/content/browser/media/webrtc_browsertest.cc b/chromium/content/browser/media/webrtc_browsertest.cc
index 58b3d3fdcfc..6b75262c66c 100644
--- a/chromium/content/browser/media/webrtc_browsertest.cc
+++ b/chromium/content/browser/media/webrtc_browsertest.cc
@@ -8,7 +8,7 @@
#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/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
@@ -19,16 +19,21 @@
namespace {
-std::string GenerateGetUserMediaCall(int min_width,
+static const char kGetUserMedia[] = "getUserMedia";
+static const char kGetUserMediaWithAnalysis[] = "getUserMediaWithAnalysis";
+
+std::string GenerateGetUserMediaCall(const char* function_name,
+ int min_width,
int max_width,
int min_height,
int max_height,
int min_frame_rate,
int max_frame_rate) {
return base::StringPrintf(
- "getUserMedia({video: {mandatory: {minWidth: %d, maxWidth: %d, "
+ "%s({video: {mandatory: {minWidth: %d, maxWidth: %d, "
"minHeight: %d, maxHeight: %d, minFrameRate: %d, maxFrameRate: %d}, "
"optional: []}});",
+ function_name,
min_width,
max_width,
min_height,
@@ -45,7 +50,7 @@ class WebrtcBrowserTest: public ContentBrowserTest {
WebrtcBrowserTest() {}
virtual ~WebrtcBrowserTest() {}
- virtual void SetUpOnMainThread() OVERRIDE {
+ virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
// We need fake devices in this test since we want to run on naked VMs. We
// assume these switches are set by default in content_browsertests.
ASSERT_TRUE(CommandLine::ForCurrentProcess()->HasSwitch(
@@ -53,7 +58,9 @@ class WebrtcBrowserTest: public ContentBrowserTest {
ASSERT_TRUE(CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUseFakeUIForMediaStream));
- ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ // The video playback will not work without a GPU, so force its use here.
+ // This may not be available on all VMs though.
+ command_line->AppendSwitch(switches::kUseGpuInTests);
}
protected:
@@ -72,7 +79,9 @@ 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) {
- GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+ ASSERT_TRUE(test_server()->Start());
+
+ GURL url(test_server()->GetURL("files/media/getusermedia.html"));
NavigateToURL(shell(), url);
EXPECT_TRUE(ExecuteJavascript("getUserMedia({video: true});"));
@@ -81,7 +90,9 @@ IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, GetVideoStreamAndStop) {
}
IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, GetAudioAndVideoStreamAndStop) {
- GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+ ASSERT_TRUE(test_server()->Start());
+
+ GURL url(test_server()->GetURL("files/media/getusermedia.html"));
NavigateToURL(shell(), url);
EXPECT_TRUE(ExecuteJavascript("getUserMedia({video: true, audio: true});"));
@@ -90,7 +101,9 @@ IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, GetAudioAndVideoStreamAndStop) {
}
IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, GetAudioAndVideoStreamAndClone) {
- GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+ ASSERT_TRUE(test_server()->Start());
+
+ GURL url(test_server()->GetURL("files/media/getusermedia.html"));
NavigateToURL(shell(), url);
EXPECT_TRUE(ExecuteJavascript("getUserMediaAndClone();"));
@@ -109,7 +122,9 @@ 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) {
- GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
+ ASSERT_TRUE(test_server()->Start());
+
+ GURL url(test_server()->GetURL("files/media/peerconnection-call.html"));
NavigateToURL(shell(), url);
EXPECT_TRUE(ExecuteJavascript("call({video: true});"));
@@ -124,7 +139,9 @@ IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, MAYBE_CanSetupVideoCall) {
#endif
IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, MAYBE_CanSetupAudioAndVideoCall) {
- GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
+ ASSERT_TRUE(test_server()->Start());
+
+ GURL url(test_server()->GetURL("files/media/peerconnection-call.html"));
NavigateToURL(shell(), url);
EXPECT_TRUE(ExecuteJavascript("call({video: true, audio: true});"));
@@ -132,7 +149,9 @@ IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, MAYBE_CanSetupAudioAndVideoCall) {
}
IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, MANUAL_CanSetupCallAndSendDtmf) {
- GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
+ ASSERT_TRUE(test_server()->Start());
+
+ GURL url(test_server()->GetURL("files/media/peerconnection-call.html"));
NavigateToURL(shell(), url);
EXPECT_TRUE(
@@ -140,8 +159,10 @@ IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, MANUAL_CanSetupCallAndSendDtmf) {
}
IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest,
- CanMakeEmptyCallThenAddStreamsAndRenegotiate) {
- GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
+ DISABLED_CanMakeEmptyCallThenAddStreamsAndRenegotiate) {
+ ASSERT_TRUE(test_server()->Start());
+
+ GURL url(test_server()->GetURL("files/media/peerconnection-call.html"));
NavigateToURL(shell(), url);
const char* kJavascript =
@@ -168,7 +189,9 @@ IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest,
#endif
IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest,
MAYBE_CanSetupAudioAndVideoCallWithoutMsidAndBundle) {
- GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
+ ASSERT_TRUE(test_server()->Start());
+
+ GURL url(test_server()->GetURL("files/media/peerconnection-call.html"));
NavigateToURL(shell(), url);
EXPECT_TRUE(ExecuteJavascript("callWithoutMsidAndBundle();"));
@@ -178,7 +201,9 @@ IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest,
// This test will make a PeerConnection-based call and test an unreliable text
// dataChannel.
IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, CallWithDataOnly) {
- GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
+ ASSERT_TRUE(test_server()->Start());
+
+ GURL url(test_server()->GetURL("files/media/peerconnection-call.html"));
NavigateToURL(shell(), url);
EXPECT_TRUE(ExecuteJavascript("callWithDataOnly();"));
@@ -195,7 +220,9 @@ 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.
IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, MAYBE_CallWithDataAndMedia) {
- GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
+ ASSERT_TRUE(test_server()->Start());
+
+ GURL url(test_server()->GetURL("files/media/peerconnection-call.html"));
NavigateToURL(shell(), url);
EXPECT_TRUE(ExecuteJavascript("callWithDataAndMedia();"));
@@ -206,13 +233,16 @@ IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, MAYBE_CallWithDataAndMedia) {
// Timing out on ARM linux bot: http://crbug.com/238490
#define MAYBE_CallWithDataAndLaterAddMedia DISABLED_CallWithDataAndLaterAddMedia
#else
-#define MAYBE_CallWithDataAndLaterAddMedia CallWithDataAndLaterAddMedia
+// Temporarily disable the test on all platforms. http://crbug.com/293252
+#define MAYBE_CallWithDataAndLaterAddMedia DISABLED_CallWithDataAndLaterAddMedia
#endif
// 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) {
- GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
+ ASSERT_TRUE(test_server()->Start());
+
+ GURL url(test_server()->GetURL("files/media/peerconnection-call.html"));
NavigateToURL(shell(), url);
EXPECT_TRUE(ExecuteJavascript("callWithDataAndLaterAddMedia();"));
@@ -230,7 +260,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) {
- GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
+ ASSERT_TRUE(test_server()->Start());
+
+ GURL url(test_server()->GetURL("files/media/peerconnection-call.html"));
NavigateToURL(shell(), url);
EXPECT_TRUE(ExecuteJavascript("callWithNewVideoMediaStream();"));
@@ -244,7 +276,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) {
- GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
+ ASSERT_TRUE(test_server()->Start());
+
+ GURL url(test_server()->GetURL("files/media/peerconnection-call.html"));
NavigateToURL(shell(), url);
EXPECT_TRUE(
@@ -254,23 +288,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) {
- GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+ ASSERT_TRUE(test_server()->Start());
+
+ GURL url(test_server()->GetURL("files/media/getusermedia.html"));
std::vector<std::string> list_of_get_user_media_calls;
list_of_get_user_media_calls.push_back(
- GenerateGetUserMediaCall(320, 320, 180, 180, 30, 30));
+ GenerateGetUserMediaCall(kGetUserMedia, 320, 320, 180, 180, 30, 30));
list_of_get_user_media_calls.push_back(
- GenerateGetUserMediaCall(320, 320, 240, 240, 30, 30));
+ GenerateGetUserMediaCall(kGetUserMedia, 320, 320, 240, 240, 30, 30));
list_of_get_user_media_calls.push_back(
- GenerateGetUserMediaCall(640, 640, 360, 360, 30, 30));
+ GenerateGetUserMediaCall(kGetUserMedia, 640, 640, 360, 360, 30, 30));
list_of_get_user_media_calls.push_back(
- GenerateGetUserMediaCall(640, 640, 480, 480, 30, 30));
+ GenerateGetUserMediaCall(kGetUserMedia, 640, 640, 480, 480, 30, 30));
list_of_get_user_media_calls.push_back(
- GenerateGetUserMediaCall(960, 960, 720, 720, 30, 30));
+ GenerateGetUserMediaCall(kGetUserMedia, 960, 960, 720, 720, 30, 30));
list_of_get_user_media_calls.push_back(
- GenerateGetUserMediaCall(1280, 1280, 720, 720, 30, 30));
+ GenerateGetUserMediaCall(kGetUserMedia, 1280, 1280, 720, 720, 30, 30));
list_of_get_user_media_calls.push_back(
- GenerateGetUserMediaCall(1920, 1920, 1080, 1080, 30, 30));
+ GenerateGetUserMediaCall(kGetUserMedia, 1920, 1920, 1080, 1080, 30, 30));
for (std::vector<std::string>::iterator const_iterator =
list_of_get_user_media_calls.begin();
@@ -283,8 +319,32 @@ 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());
+
+ GURL url(test_server()->GetURL("files/media/getusermedia.html"));
+
+ std::string constraints_4_3 = GenerateGetUserMediaCall(
+ kGetUserMediaWithAnalysis, 640, 640, 480, 480, 30, 30);
+ std::string constraints_16_9 = GenerateGetUserMediaCall(
+ kGetUserMediaWithAnalysis, 640, 640, 360, 360, 30, 30);
+
+ // TODO(mcasas): add more aspect ratios, in particular 16:10 crbug.com/275594.
+
+ NavigateToURL(shell(), url);
+ EXPECT_TRUE(ExecuteJavascript(constraints_4_3));
+ ExpectTitle("4:3 letterbox");
+
+ NavigateToURL(shell(), url);
+ EXPECT_TRUE(ExecuteJavascript(constraints_16_9));
+ ExpectTitle("16:9 letterbox");
+}
+
IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, AddTwoMediaStreamsToOnePC) {
- GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
+ ASSERT_TRUE(test_server()->Start());
+
+ GURL url(test_server()->GetURL("files/media/peerconnection-call.html"));
NavigateToURL(shell(), url);
EXPECT_TRUE(
diff --git a/chromium/content/browser/media/webrtc_internals.cc b/chromium/content/browser/media/webrtc_internals.cc
index f8bcdc3d321..e94447a3e0a 100644
--- a/chromium/content/browser/media/webrtc_internals.cc
+++ b/chromium/content/browser/media/webrtc_internals.cc
@@ -65,7 +65,7 @@ void WebRTCInternals::OnAddPeerConnection(int render_process_id,
dict->SetString("url", url);
peer_connection_data_.Append(dict);
- if (observers_.size() > 0)
+ if (observers_.might_have_observers())
SendUpdate("addPeerConnection", dict);
}
@@ -85,7 +85,7 @@ void WebRTCInternals::OnRemovePeerConnection(ProcessId pid, int lid) {
peer_connection_data_.Remove(i, NULL);
- if (observers_.size() > 0) {
+ if (observers_.might_have_observers()) {
base::DictionaryValue id;
id.SetInteger("pid", static_cast<int>(pid));
id.SetInteger("lid", lid);
@@ -123,7 +123,7 @@ void WebRTCInternals::OnUpdatePeerConnection(
log_entry->SetString("value", value);
log->Append(log_entry);
- if (observers_.size() > 0) {
+ if (observers_.might_have_observers()) {
base::DictionaryValue update;
update.SetInteger("pid", static_cast<int>(pid));
update.SetInteger("lid", lid);
@@ -138,7 +138,7 @@ void WebRTCInternals::OnUpdatePeerConnection(
void WebRTCInternals::OnAddStats(base::ProcessId pid, int lid,
const base::ListValue& value) {
- if (observers_.size() == 0)
+ if (!observers_.might_have_observers())
return;
base::DictionaryValue dict;
@@ -165,7 +165,7 @@ void WebRTCInternals::RemoveObserver(WebRTCInternalsUIObserver *observer) {
}
void WebRTCInternals::SendAllUpdates() {
- if (observers_.size() > 0)
+ if (observers_.might_have_observers())
SendUpdate("updateAllPeerConnections", &peer_connection_data_);
}
@@ -184,7 +184,7 @@ void WebRTCInternals::StopRtpRecording() {
}
void WebRTCInternals::SendUpdate(const string& command, base::Value* value) {
- DCHECK_GT(observers_.size(), (size_t)0);
+ DCHECK(observers_.might_have_observers());
FOR_EACH_OBSERVER(WebRTCInternalsUIObserver,
observers_,
@@ -216,7 +216,7 @@ void WebRTCInternals::OnRendererExit(int render_process_id) {
record->GetInteger("rid", &this_rid);
if (this_rid == render_process_id) {
- if (observers_.size() > 0) {
+ if (observers_.might_have_observers()) {
int lid = 0, pid = 0;
record->GetInteger("lid", &lid);
record->GetInteger("pid", &pid);
diff --git a/chromium/content/browser/media/webrtc_internals_browsertest.cc b/chromium/content/browser/media/webrtc_internals_browsertest.cc
index 19c25741822..b45827623b4 100644
--- a/chromium/content/browser/media/webrtc_internals_browsertest.cc
+++ b/chromium/content/browser/media/webrtc_internals_browsertest.cc
@@ -9,7 +9,7 @@
#include "base/values.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
-#include "content/shell/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
@@ -118,10 +118,17 @@ class PeerConnectionEntry {
static const int64 FAKE_TIME_STAMP = 3600000;
-class WebRTCInternalsBrowserTest: public ContentBrowserTest {
+#if defined(OS_WIN)
+// All tests are flaky on Windows: crbug.com/277322.
+#define MAYBE_WebRTCInternalsBrowserTest DISABLED_WebRTCInternalsBrowserTest
+#else
+#define MAYBE_WebRTCInternalsBrowserTest WebRTCInternalsBrowserTest
+#endif
+
+class MAYBE_WebRTCInternalsBrowserTest: public ContentBrowserTest {
public:
- WebRTCInternalsBrowserTest() {}
- virtual ~WebRTCInternalsBrowserTest() {}
+ MAYBE_WebRTCInternalsBrowserTest() {}
+ virtual ~MAYBE_WebRTCInternalsBrowserTest() {}
virtual void SetUpOnMainThread() OVERRIDE {
// We need fake devices in this test since we want to run on naked VMs. We
@@ -395,7 +402,8 @@ class WebRTCInternalsBrowserTest: public ContentBrowserTest {
}
};
-IN_PROC_BROWSER_TEST_F(WebRTCInternalsBrowserTest, AddAndRemovePeerConnection) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRTCInternalsBrowserTest,
+ AddAndRemovePeerConnection) {
GURL url("chrome://webrtc-internals");
NavigateToURL(shell(), url);
@@ -416,7 +424,8 @@ IN_PROC_BROWSER_TEST_F(WebRTCInternalsBrowserTest, AddAndRemovePeerConnection) {
VerifyNoElementWithId(pc_2.getIdString());
}
-IN_PROC_BROWSER_TEST_F(WebRTCInternalsBrowserTest, UpdateAllPeerConnections) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRTCInternalsBrowserTest,
+ UpdateAllPeerConnections) {
GURL url("chrome://webrtc-internals");
NavigateToURL(shell(), url);
@@ -433,7 +442,7 @@ IN_PROC_BROWSER_TEST_F(WebRTCInternalsBrowserTest, UpdateAllPeerConnections) {
VerifyPeerConnectionEntry(pc_1);
}
-IN_PROC_BROWSER_TEST_F(WebRTCInternalsBrowserTest, UpdatePeerConnection) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRTCInternalsBrowserTest, UpdatePeerConnection) {
GURL url("chrome://webrtc-internals");
NavigateToURL(shell(), url);
@@ -470,7 +479,7 @@ IN_PROC_BROWSER_TEST_F(WebRTCInternalsBrowserTest, UpdatePeerConnection) {
}
// Tests that adding random named stats updates the dataSeries and graphs.
-IN_PROC_BROWSER_TEST_F(WebRTCInternalsBrowserTest, AddStats) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRTCInternalsBrowserTest, AddStats) {
GURL url("chrome://webrtc-internals");
NavigateToURL(shell(), url);
@@ -496,7 +505,7 @@ IN_PROC_BROWSER_TEST_F(WebRTCInternalsBrowserTest, AddStats) {
}
// Tests that the bandwidth estimation values are drawn on a single graph.
-IN_PROC_BROWSER_TEST_F(WebRTCInternalsBrowserTest, BweCompoundGraph) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRTCInternalsBrowserTest, BweCompoundGraph) {
GURL url("chrome://webrtc-internals");
NavigateToURL(shell(), url);
@@ -536,7 +545,7 @@ IN_PROC_BROWSER_TEST_F(WebRTCInternalsBrowserTest, BweCompoundGraph) {
// Tests that the total packet/byte count is converted to count per second,
// and the converted data is drawn.
-IN_PROC_BROWSER_TEST_F(WebRTCInternalsBrowserTest, ConvertedGraphs) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRTCInternalsBrowserTest, ConvertedGraphs) {
GURL url("chrome://webrtc-internals");
NavigateToURL(shell(), url);
@@ -575,16 +584,11 @@ IN_PROC_BROWSER_TEST_F(WebRTCInternalsBrowserTest, ConvertedGraphs) {
}
}
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
// Timing out on ARM linux bot: http://crbug.com/238490
-#define MAYBE_WithRealPeerConnectionCall DISABLED_WithRealPeerConnectionCall
-#else
-#define MAYBE_WithRealPeerConnectionCall WithRealPeerConnectionCall
-#endif
-
+// Disabling due to failure on Linux, Mac, Win: http://crbug.com/272413
// Sanity check of the page content under a real PeerConnection call.
-IN_PROC_BROWSER_TEST_F(WebRTCInternalsBrowserTest,
- MAYBE_WithRealPeerConnectionCall) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRTCInternalsBrowserTest,
+ DISABLED_WithRealPeerConnectionCall) {
// Start a peerconnection call in the first window.
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
@@ -666,7 +670,7 @@ IN_PROC_BROWSER_TEST_F(WebRTCInternalsBrowserTest,
EXPECT_GT(count, 0);
}
-IN_PROC_BROWSER_TEST_F(WebRTCInternalsBrowserTest, CreatePageDump) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRTCInternalsBrowserTest, CreatePageDump) {
GURL url("chrome://webrtc-internals");
NavigateToURL(shell(), url);
diff --git a/chromium/content/browser/mime_registry_message_filter.cc b/chromium/content/browser/mime_registry_message_filter.cc
index 49a050084c9..f23cc004e4b 100644
--- a/chromium/content/browser/mime_registry_message_filter.cc
+++ b/chromium/content/browser/mime_registry_message_filter.cc
@@ -30,8 +30,6 @@ bool MimeRegistryMessageFilter::OnMessageReceived(const IPC::Message& message,
OnGetMimeTypeFromExtension)
IPC_MESSAGE_HANDLER(MimeRegistryMsg_GetMimeTypeFromFile,
OnGetMimeTypeFromFile)
- IPC_MESSAGE_HANDLER(MimeRegistryMsg_GetPreferredExtensionForMimeType,
- OnGetPreferredExtensionForMimeType)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -47,9 +45,4 @@ void MimeRegistryMessageFilter::OnGetMimeTypeFromFile(
net::GetMimeTypeFromFile(file_path, mime_type);
}
-void MimeRegistryMessageFilter::OnGetPreferredExtensionForMimeType(
- const std::string& mime_type, base::FilePath::StringType* extension) {
- net::GetPreferredExtensionForMimeType(mime_type, extension);
-}
-
} // namespace content
diff --git a/chromium/content/browser/mime_registry_message_filter.h b/chromium/content/browser/mime_registry_message_filter.h
index 4a719a5f2f1..e86fe190b1d 100644
--- a/chromium/content/browser/mime_registry_message_filter.h
+++ b/chromium/content/browser/mime_registry_message_filter.h
@@ -27,9 +27,6 @@ class MimeRegistryMessageFilter : public BrowserMessageFilter {
std::string* mime_type);
void OnGetMimeTypeFromFile(const base::FilePath& file_path,
std::string* mime_type);
- void OnGetPreferredExtensionForMimeType(
- const std::string& mime_type,
- base::FilePath::StringType* extension);
};
} // namespace content
diff --git a/chromium/content/browser/net/sqlite_persistent_cookie_store.cc b/chromium/content/browser/net/sqlite_persistent_cookie_store.cc
index c23692d4750..517a8c18a16 100644
--- a/chromium/content/browser/net/sqlite_persistent_cookie_store.cc
+++ b/chromium/content/browser/net/sqlite_persistent_cookie_store.cc
@@ -1198,13 +1198,15 @@ net::CookieStore* CreatePersistentCookieStore(
const base::FilePath& path,
bool restore_old_session_cookies,
quota::SpecialStoragePolicy* storage_policy,
- net::CookieMonster::Delegate* cookie_monster_delegate) {
+ net::CookieMonster::Delegate* cookie_monster_delegate,
+ const scoped_refptr<base::SequencedTaskRunner>& background_task_runner) {
SQLitePersistentCookieStore* persistent_store =
new SQLitePersistentCookieStore(
path,
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
- BrowserThread::GetBlockingPool()->GetSequencedTaskRunner(
- BrowserThread::GetBlockingPool()->GetSequenceToken()),
+ background_task_runner.get() ? background_task_runner :
+ BrowserThread::GetBlockingPool()->GetSequencedTaskRunner(
+ BrowserThread::GetBlockingPool()->GetSequenceToken()),
restore_old_session_cookies,
storage_policy);
net::CookieMonster* cookie_monster =
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 4f627062ec5..e71b56b7a80 100644
--- a/chromium/content/browser/net/sqlite_persistent_cookie_store_perftest.cc
+++ b/chromium/content/browser/net/sqlite_persistent_cookie_store_perftest.cc
@@ -7,10 +7,10 @@
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/files/scoped_temp_dir.h"
-#include "base/perftimer.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/waitable_event.h"
+#include "base/test/perf_time_logger.h"
#include "base/test/sequenced_worker_pool_owner.h"
#include "base/threading/sequenced_worker_pool.h"
#include "net/cookies/canonical_cookie.h"
@@ -118,7 +118,7 @@ class SQLitePersistentCookieStorePerfTest : public testing::Test {
TEST_F(SQLitePersistentCookieStorePerfTest, TestLoadForKeyPerformance) {
for (int domain_num = 0; domain_num < 3; ++domain_num) {
std::string domain_name(base::StringPrintf("domain_%d.com", domain_num));
- PerfTimeLogger timer(
+ base::PerfTimeLogger timer(
("Load cookies for the eTLD+1 " + domain_name).c_str());
store_->LoadCookiesForKey(domain_name,
base::Bind(&SQLitePersistentCookieStorePerfTest::OnKeyLoaded,
@@ -132,7 +132,7 @@ TEST_F(SQLitePersistentCookieStorePerfTest, TestLoadForKeyPerformance) {
// Test the performance of load
TEST_F(SQLitePersistentCookieStorePerfTest, TestLoadPerformance) {
- PerfTimeLogger timer("Load all cookies");
+ base::PerfTimeLogger timer("Load all cookies");
Load();
timer.Done();
diff --git a/chromium/content/browser/net/view_blob_internals_job_factory.cc b/chromium/content/browser/net/view_blob_internals_job_factory.cc
index e877a418e54..85356e5aae5 100644
--- a/chromium/content/browser/net/view_blob_internals_job_factory.cc
+++ b/chromium/content/browser/net/view_blob_internals_job_factory.cc
@@ -21,9 +21,9 @@ bool ViewBlobInternalsJobFactory::IsSupportedURL(const GURL& url) {
net::URLRequestJob* ViewBlobInternalsJobFactory::CreateJobForRequest(
net::URLRequest* request,
net::NetworkDelegate* network_delegate,
- webkit_blob::BlobStorageController* blob_storage_controller) {
+ webkit_blob::BlobStorageContext* blob_storage_context) {
return new webkit_blob::ViewBlobInternalsJob(
- request, network_delegate, blob_storage_controller);
+ request, network_delegate, blob_storage_context);
}
} // namespace content
diff --git a/chromium/content/browser/net/view_blob_internals_job_factory.h b/chromium/content/browser/net/view_blob_internals_job_factory.h
index 0843e0651e6..4d4b60abf4c 100644
--- a/chromium/content/browser/net/view_blob_internals_job_factory.h
+++ b/chromium/content/browser/net/view_blob_internals_job_factory.h
@@ -11,7 +11,7 @@ class URLRequest;
class URLRequestJob;
} // namespace net
namespace webkit_blob {
-class BlobStorageController;
+class BlobStorageContext;
} // webkit_blob
class GURL;
@@ -24,7 +24,7 @@ class ViewBlobInternalsJobFactory {
static net::URLRequestJob* CreateJobForRequest(
net::URLRequest* request,
net::NetworkDelegate* network_delegate,
- webkit_blob::BlobStorageController* blob_storage_controller);
+ webkit_blob::BlobStorageContext* blob_storage_context);
};
} // namespace content
diff --git a/chromium/content/browser/notification_service_impl.cc b/chromium/content/browser/notification_service_impl.cc
index 49132883f18..27de8579fe8 100644
--- a/chromium/content/browser/notification_service_impl.cc
+++ b/chromium/content/browser/notification_service_impl.cc
@@ -83,7 +83,7 @@ void NotificationServiceImpl::RemoveObserver(NotificationObserver* observer,
observers_[type][source.map_key()];
if (observer_list) {
observer_list->RemoveObserver(observer);
- if (!observer_list->size()) {
+ if (!observer_list->might_have_observers()) {
observers_[type].erase(source.map_key());
delete observer_list;
}
diff --git a/chromium/content/browser/plugin_browsertest.cc b/chromium/content/browser/plugin_browsertest.cc
index c1dfa1f1953..37e1fa9449c 100644
--- a/chromium/content/browser/plugin_browsertest.cc
+++ b/chromium/content/browser/plugin_browsertest.cc
@@ -9,8 +9,8 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
+#include "content/shell/browser/shell.h"
#include "content/shell/common/shell_switches.h"
-#include "content/shell/shell.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"
diff --git a/chromium/content/browser/plugin_data_remover_impl_browsertest.cc b/chromium/content/browser/plugin_data_remover_impl_browsertest.cc
index 37672eef947..8308a51ba51 100644
--- a/chromium/content/browser/plugin_data_remover_impl_browsertest.cc
+++ b/chromium/content/browser/plugin_data_remover_impl_browsertest.cc
@@ -11,7 +11,7 @@
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/test_utils.h"
-#include "content/shell/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
namespace content {
diff --git a/chromium/content/browser/plugin_process_host.cc b/chromium/content/browser/plugin_process_host.cc
index bffd16ef50e..86d313472e4 100644
--- a/chromium/content/browser/plugin_process_host.cc
+++ b/chromium/content/browser/plugin_process_host.cc
@@ -22,6 +22,7 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/browser_child_process_host_impl.h"
+#include "content/browser/loader/resource_message_filter.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/plugin_service_impl.h"
#include "content/common/child_process_host_impl.h"
@@ -31,9 +32,11 @@
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/plugin_service.h"
+#include "content/public/browser/resource_context.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/process_type.h"
#include "ipc/ipc_switches.h"
+#include "net/url_request/url_request_context_getter.h"
#include "ui/base/ui_base_switches.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gl/gl_switches.h"
@@ -220,7 +223,7 @@ bool PluginProcessHost::Init(const WebPluginInfo& info) {
cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id);
#if defined(OS_POSIX)
- base::EnvironmentVector env;
+ base::EnvironmentMap env;
#if defined(OS_MACOSX) && !defined(__LP64__)
if (!browser_command_line.HasSwitch(switches::kDisableCarbonInterposing)) {
std::string interpose_list = GetContentClient()->GetCarbonInterposePath();
@@ -233,8 +236,7 @@ bool PluginProcessHost::Init(const WebPluginInfo& info) {
interpose_list.insert(0, existing_list);
}
}
- env.push_back(std::pair<std::string, std::string>(
- kDYLDInsertLibrariesKey, interpose_list));
+ env[kDYLDInsertLibrariesKey] = interpose_list;
}
#endif
#endif
@@ -254,6 +256,16 @@ bool PluginProcessHost::Init(const WebPluginInfo& info) {
// been destroyed.
process_->SetTerminateChildOnShutdown(false);
+ ResourceMessageFilter::GetContextsCallback get_contexts_callback(
+ base::Bind(&PluginProcessHost::GetContexts,
+ base::Unretained(this)));
+
+ // TODO(jam): right now we're passing NULL for appcache, blob storage, and
+ // file system. If NPAPI plugins actually use this, we'll have to plumb them.
+ ResourceMessageFilter* resource_message_filter = new ResourceMessageFilter(
+ process_->GetData().id, PROCESS_TYPE_PLUGIN, NULL, NULL, NULL,
+ get_contexts_callback);
+ process_->GetHost()->AddFilter(resource_message_filter);
return true;
}
@@ -271,6 +283,8 @@ bool PluginProcessHost::OnMessageReceived(const IPC::Message& msg) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PluginProcessHost, msg)
IPC_MESSAGE_HANDLER(PluginProcessHostMsg_ChannelCreated, OnChannelCreated)
+ IPC_MESSAGE_HANDLER(PluginProcessHostMsg_ChannelDestroyed,
+ OnChannelDestroyed)
#if defined(OS_WIN)
IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginWindowDestroyed,
OnPluginWindowDestroyed)
@@ -292,7 +306,6 @@ bool PluginProcessHost::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
- DCHECK(handled);
return handled;
}
@@ -329,21 +342,6 @@ void PluginProcessHost::CancelRequests() {
}
}
-// static
-void PluginProcessHost::CancelPendingRequestsForResourceContext(
- ResourceContext* context) {
- for (PluginProcessHostIterator host_it; !host_it.Done(); ++host_it) {
- PluginProcessHost* host = *host_it;
- for (size_t i = 0; i < host->pending_requests_.size(); ++i) {
- if (host->pending_requests_[i]->GetResourceContext() == context) {
- host->pending_requests_[i]->OnError();
- host->pending_requests_.erase(host->pending_requests_.begin() + i);
- --i;
- }
- }
- }
-}
-
void PluginProcessHost::OpenChannelToPlugin(Client* client) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
@@ -409,9 +407,22 @@ void PluginProcessHost::OnChannelCreated(
const IPC::ChannelHandle& channel_handle) {
Client* client = sent_requests_.front();
- if (client)
+ if (client) {
+ resource_context_map_[client->ID()] = client->GetResourceContext();
client->OnChannelOpened(channel_handle);
+ }
sent_requests_.pop_front();
}
+void PluginProcessHost::OnChannelDestroyed(int renderer_id) {
+ 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];
+ *request_context = (*resource_context)->GetRequestContext();
+}
+
} // namespace content
diff --git a/chromium/content/browser/plugin_process_host.h b/chromium/content/browser/plugin_process_host.h
index 61ce44db221..75c667daf0f 100644
--- a/chromium/content/browser/plugin_process_host.h
+++ b/chromium/content/browser/plugin_process_host.h
@@ -8,6 +8,7 @@
#include "build/build_config.h"
#include <list>
+#include <map>
#include <set>
#include <string>
#include <vector>
@@ -22,6 +23,9 @@
#include "content/public/common/webplugininfo.h"
#include "ipc/ipc_channel_proxy.h"
#include "ui/gfx/native_widget_types.h"
+#include "webkit/common/resource_type.h"
+
+struct ResourceHostMsg_Request;
namespace gfx {
class Rect;
@@ -31,6 +35,10 @@ namespace IPC {
struct ChannelHandle;
}
+namespace net {
+class URLRequestContext;
+}
+
namespace content {
class BrowserChildProcessHostImpl;
class ResourceContext;
@@ -87,9 +95,6 @@ class CONTENT_EXPORT PluginProcessHost : public BrowserChildProcessHostDelegate,
// OnChannelOpened in the client is called.
void OpenChannelToPlugin(Client* client);
- // Cancels all pending channel requests for the given resource context.
- static void CancelPendingRequestsForResourceContext(ResourceContext* context);
-
// This function is called to cancel pending requests to open new channels.
void CancelPendingRequest(Client* client);
@@ -125,6 +130,7 @@ class CONTENT_EXPORT PluginProcessHost : public BrowserChildProcessHostDelegate,
// Message handlers.
void OnChannelCreated(const IPC::ChannelHandle& channel_handle);
+ void OnChannelDestroyed(int renderer_id);
#if defined(OS_WIN)
void OnPluginWindowDestroyed(HWND window, HWND parent);
@@ -148,6 +154,11 @@ class CONTENT_EXPORT PluginProcessHost : public BrowserChildProcessHostDelegate,
void CancelRequests();
+ // Callback for ResourceMessageFilter.
+ void GetContexts(const ResourceHostMsg_Request& request,
+ ResourceContext** resource_context,
+ net::URLRequestContext** request_context);
+
// These are channel requests that we are waiting to send to the
// plugin process once the channel is opened.
std::vector<Client*> pending_requests_;
@@ -174,6 +185,10 @@ 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;
+ ResourceContextMap resource_context_map_;
+
scoped_ptr<BrowserChildProcessHostImpl> process_;
DISALLOW_COPY_AND_ASSIGN(PluginProcessHost);
diff --git a/chromium/content/browser/plugin_service_impl.cc b/chromium/content/browser/plugin_service_impl.cc
index 6682a4d4604..b46af4fbeff 100644
--- a/chromium/content/browser/plugin_service_impl.cc
+++ b/chromium/content/browser/plugin_service_impl.cc
@@ -33,7 +33,7 @@
#if defined(OS_WIN)
#include "content/common/plugin_constants_win.h"
-#include "ui/base/win/hwnd_util.h"
+#include "ui/gfx/win/hwnd_util.h"
#endif
#if defined(OS_POSIX)
@@ -328,8 +328,7 @@ PluginProcessHost* PluginServiceImpl::FindOrStartNpapiPluginProcess(
PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiPluginProcess(
int render_process_id,
const base::FilePath& plugin_path,
- const base::FilePath& profile_data_directory,
- PpapiPluginProcessHost::PluginClient* client) {
+ const base::FilePath& profile_data_directory) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path))
@@ -356,8 +355,7 @@ PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiPluginProcess(
// This plugin isn't loaded by any plugin process, so create a new process.
return PpapiPluginProcessHost::CreatePluginHost(
- *info, profile_data_directory,
- client->GetResourceContext()->GetHostResolver());
+ *info, profile_data_directory);
}
PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiBrokerProcess(
@@ -413,7 +411,7 @@ void PluginServiceImpl::OpenChannelToPpapiPlugin(
const base::FilePath& profile_data_directory,
PpapiPluginProcessHost::PluginClient* client) {
PpapiPluginProcessHost* plugin_host = FindOrStartPpapiPluginProcess(
- render_process_id, plugin_path, profile_data_directory, client);
+ render_process_id, plugin_path, profile_data_directory);
if (plugin_host) {
plugin_host->OpenChannelToPlugin(client);
} else {
@@ -660,7 +658,7 @@ void PluginServiceImpl::RegisterPepperPlugins() {
PepperPluginInfo* PluginServiceImpl::GetRegisteredPpapiPluginInfo(
const base::FilePath& plugin_path) {
PepperPluginInfo* info = NULL;
- for (size_t i = 0; i < ppapi_plugins_.size(); i++) {
+ for (size_t i = 0; i < ppapi_plugins_.size(); ++i) {
if (ppapi_plugins_[i].path == plugin_path) {
info = &ppapi_plugins_[i];
break;
@@ -790,7 +788,8 @@ void PluginServiceImpl::GetInternalPlugins(
}
bool PluginServiceImpl::NPAPIPluginsSupported() {
-#if defined(OS_WIN) || defined(OS_MACOSX) || (defined(OS_LINUX) && !defined(USE_AURA))
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_BSD) || \
+ (defined(OS_LINUX) && !defined(USE_AURA))
return true;
#else
return false;
@@ -839,7 +838,7 @@ bool PluginServiceImpl::GetPluginInfoFromWindow(
}
bool PluginServiceImpl::IsPluginWindow(HWND window) {
- return ui::GetClassName(window) == base::string16(kNativeWindowClassName);
+ return gfx::GetClassName(window) == base::string16(kNativeWindowClassName);
}
#endif
diff --git a/chromium/content/browser/plugin_service_impl.h b/chromium/content/browser/plugin_service_impl.h
index 6d358fd21a9..11fb257e99b 100644
--- a/chromium/content/browser/plugin_service_impl.h
+++ b/chromium/content/browser/plugin_service_impl.h
@@ -131,8 +131,7 @@ class CONTENT_EXPORT PluginServiceImpl
PpapiPluginProcessHost* FindOrStartPpapiPluginProcess(
int render_process_id,
const base::FilePath& plugin_path,
- const base::FilePath& profile_data_directory,
- PpapiPluginProcessHost::PluginClient* client);
+ const base::FilePath& profile_data_directory);
PpapiPluginProcessHost* FindOrStartPpapiBrokerProcess(
int render_process_id, const base::FilePath& plugin_path);
diff --git a/chromium/content/browser/plugin_service_impl_browsertest.cc b/chromium/content/browser/plugin_service_impl_browsertest.cc
index 1abf725e435..e99f3e537c6 100644
--- a/chromium/content/browser/plugin_service_impl_browsertest.cc
+++ b/chromium/content/browser/plugin_service_impl_browsertest.cc
@@ -15,7 +15,7 @@
#include "content/public/common/content_switches.h"
#include "content/public/test/test_browser_thread.h"
#include "content/public/test/test_utils.h"
-#include "content/shell/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "testing/gmock/include/gmock/gmock.h"
diff --git a/chromium/content/browser/power_monitor_message_broadcaster.cc b/chromium/content/browser/power_monitor_message_broadcaster.cc
index 77abcb959f9..23de161b05c 100644
--- a/chromium/content/browser/power_monitor_message_broadcaster.cc
+++ b/chromium/content/browser/power_monitor_message_broadcaster.cc
@@ -36,4 +36,4 @@ void PowerMonitorMessageBroadcaster::OnResume() {
sender_->Send(new PowerMonitorMsg_Resume());
}
-} // namespace content \ No newline at end of file
+} // namespace content
diff --git a/chromium/content/browser/power_monitor_message_broadcaster.h b/chromium/content/browser/power_monitor_message_broadcaster.h
index f0e3a207e2d..04af601d719 100644
--- a/chromium/content/browser/power_monitor_message_broadcaster.h
+++ b/chromium/content/browser/power_monitor_message_broadcaster.h
@@ -38,4 +38,4 @@ class CONTENT_EXPORT PowerMonitorMessageBroadcaster
} // namespace base
-#endif // CONTENT_BROWSER_POWER_MONITOR_MESSAGE_BROADCASTER_H_ \ No newline at end of file
+#endif // CONTENT_BROWSER_POWER_MONITOR_MESSAGE_BROADCASTER_H_
diff --git a/chromium/content/browser/power_save_blocker_chromeos.cc b/chromium/content/browser/power_save_blocker_chromeos.cc
index 9eda5c45027..f9a6722f8d2 100644
--- a/chromium/content/browser/power_save_blocker_chromeos.cc
+++ b/chromium/content/browser/power_save_blocker_chromeos.cc
@@ -27,10 +27,8 @@ class PowerSaveBlockerImpl::Delegate
void ApplyBlock() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (!chromeos::DBusThreadManager::IsInitialized()) {
- LOG(WARNING) << "DBusThreadManager not initialized";
+ if (!chromeos::DBusThreadManager::IsInitialized())
return;
- }
chromeos::PowerPolicyController* controller =
chromeos::DBusThreadManager::Get()->GetPowerPolicyController();
@@ -48,10 +46,9 @@ class PowerSaveBlockerImpl::Delegate
void RemoveBlock() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (!chromeos::DBusThreadManager::IsInitialized()) {
- LOG(WARNING) << "DBusThreadManager not initialized";
+ if (!chromeos::DBusThreadManager::IsInitialized())
return;
- }
+
chromeos::DBusThreadManager::Get()->GetPowerPolicyController()->
RemoveWakeLock(block_id_);
}
diff --git a/chromium/content/browser/power_save_blocker_x11.cc b/chromium/content/browser/power_save_blocker_x11.cc
index d955643f281..f55fac9580a 100644
--- a/chromium/content/browser/power_save_blocker_x11.cc
+++ b/chromium/content/browser/power_save_blocker_x11.cc
@@ -29,11 +29,12 @@
#include "dbus/message.h"
#include "dbus/object_path.h"
#include "dbus/object_proxy.h"
+#include "ui/gfx/x/x11_types.h"
#if defined(TOOLKIT_GTK)
#include "base/message_loop/message_pump_gtk.h"
#else
-#include "base/message_loop/message_pump_aurax11.h"
+#include "base/message_loop/message_pump_x11.h"
#endif
namespace {
@@ -298,7 +299,7 @@ void PowerSaveBlockerImpl::Delegate::RemoveBlock(DBusAPI api) {
// static
bool PowerSaveBlockerImpl::Delegate::DPMSEnabled() {
- Display* display = base::MessagePumpForUI::GetDefaultXDisplay();
+ XDisplay* display = base::MessagePumpForUI::GetDefaultXDisplay();
BOOL enabled = false;
int dummy;
if (DPMSQueryExtension(display, &dummy, &dummy) && DPMSCapable(display)) {
diff --git a/chromium/content/browser/ppapi_plugin_process_host.cc b/chromium/content/browser/ppapi_plugin_process_host.cc
index c9aa6994660..ecbbfd6bfce 100644
--- a/chromium/content/browser/ppapi_plugin_process_host.cc
+++ b/chromium/content/browser/ppapi_plugin_process_host.cc
@@ -114,10 +114,9 @@ PpapiPluginProcessHost::~PpapiPluginProcessHost() {
// static
PpapiPluginProcessHost* PpapiPluginProcessHost::CreatePluginHost(
const PepperPluginInfo& info,
- const base::FilePath& profile_data_directory,
- net::HostResolver* host_resolver) {
+ const base::FilePath& profile_data_directory) {
PpapiPluginProcessHost* plugin_host = new PpapiPluginProcessHost(
- info, profile_data_directory, host_resolver);
+ info, profile_data_directory);
if (plugin_host->Init(info))
return plugin_host;
@@ -206,8 +205,7 @@ void PpapiPluginProcessHost::OpenChannelToPlugin(Client* client) {
PpapiPluginProcessHost::PpapiPluginProcessHost(
const PepperPluginInfo& info,
- const base::FilePath& profile_data_directory,
- net::HostResolver* host_resolver)
+ const base::FilePath& profile_data_directory)
: permissions_(
ppapi::PpapiPermissions::GetForCommandLine(info.permissions)),
profile_data_directory_(profile_data_directory),
@@ -215,13 +213,11 @@ PpapiPluginProcessHost::PpapiPluginProcessHost(
process_.reset(new BrowserChildProcessHostImpl(
PROCESS_TYPE_PPAPI_PLUGIN, this));
- filter_ = new PepperMessageFilter(permissions_, host_resolver);
-
host_impl_.reset(new BrowserPpapiHostImpl(this, permissions_, info.name,
info.path, profile_data_directory,
- false,
- filter_));
+ false));
+ filter_ = new PepperMessageFilter();
process_->GetHost()->AddFilter(filter_.get());
process_->GetHost()->AddFilter(host_impl_->message_filter().get());
@@ -243,8 +239,7 @@ PpapiPluginProcessHost::PpapiPluginProcessHost()
host_impl_.reset(new BrowserPpapiHostImpl(this, permissions,
std::string(), base::FilePath(),
base::FilePath(),
- false,
- NULL));
+ false));
}
bool PpapiPluginProcessHost::Init(const PepperPluginInfo& info) {
@@ -333,7 +328,7 @@ bool PpapiPluginProcessHost::Init(const PepperPluginInfo& info) {
new PpapiPluginSandboxedProcessLauncherDelegate(is_broker_),
#elif defined(OS_POSIX)
use_zygote,
- base::EnvironmentVector(),
+ base::EnvironmentMap(),
#endif
cmd_line);
return true;
diff --git a/chromium/content/browser/ppapi_plugin_process_host.h b/chromium/content/browser/ppapi_plugin_process_host.h
index 78d6bd63c50..87c79c31d2a 100644
--- a/chromium/content/browser/ppapi_plugin_process_host.h
+++ b/chromium/content/browser/ppapi_plugin_process_host.h
@@ -21,10 +21,6 @@
#include "ipc/ipc_sender.h"
#include "ppapi/shared_impl/ppapi_permissions.h"
-namespace net {
-class HostResolver;
-}
-
namespace content {
class BrowserChildProcessHostImpl;
class ResourceContext;
@@ -76,8 +72,7 @@ class PpapiPluginProcessHost : public BrowserChildProcessHostDelegate,
static PpapiPluginProcessHost* CreatePluginHost(
const PepperPluginInfo& info,
- const base::FilePath& profile_data_directory,
- net::HostResolver* host_resolver);
+ const base::FilePath& profile_data_directory);
static PpapiPluginProcessHost* CreateBrokerHost(
const PepperPluginInfo& info);
@@ -122,8 +117,7 @@ class PpapiPluginProcessHost : public BrowserChildProcessHostDelegate,
// Constructors for plugin and broker process hosts, respectively.
// You must call Init before doing anything else.
PpapiPluginProcessHost(const PepperPluginInfo& info,
- const base::FilePath& profile_data_directory,
- net::HostResolver* host_resolver);
+ const base::FilePath& profile_data_directory);
PpapiPluginProcessHost();
// Actually launches the process with the given plugin info. Returns true
diff --git a/chromium/content/browser/renderer_host/DEPS b/chromium/content/browser/renderer_host/DEPS
index 34decdb0223..0848d364726 100644
--- a/chromium/content/browser/renderer_host/DEPS
+++ b/chromium/content/browser/renderer_host/DEPS
@@ -5,10 +5,6 @@ include_rules = [
"+third_party/zlib",
"+third_party/libyuv",
- # For single-process mode.
- "+content/renderer/render_process_impl.h",
- "+content/renderer/render_thread_impl.h",
-
# The renderer_host files should only call upwards in the layering via the
# delegate interfaces.
"-content/browser/web_contents",
diff --git a/chromium/content/browser/renderer_host/backing_store_gtk.cc b/chromium/content/browser/renderer_host/backing_store_gtk.cc
index 62365bed873..2eed33ace2f 100644
--- a/chromium/content/browser/renderer_host/backing_store_gtk.cc
+++ b/chromium/content/browser/renderer_host/backing_store_gtk.cc
@@ -29,10 +29,10 @@
#include "skia/ext/platform_canvas.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/gtk/gtk_signal.h"
-#include "ui/base/x/x11_util.h"
#include "ui/base/x/x11_util_internal.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/rect_conversions.h"
+#include "ui/gfx/x/x11_types.h"
#include "ui/surface/transport_dib.h"
namespace content {
@@ -59,7 +59,7 @@ static const int kMaxVideoLayerSize = 23170;
// Destroys the image and the associated shared memory structures. This is a
// helper function for code using shared memory.
-void DestroySharedImage(Display* display,
+void DestroySharedImage(XDisplay* display,
XImage* image,
XShmSegmentInfo* shminfo) {
XShmDetach(display, shminfo);
@@ -72,7 +72,7 @@ void DestroySharedImage(Display* display,
// XSyncExtension to push a callback into the X11 event queue and get a
// callback instead of blocking until the event queue is cleared.
//
-// TODO(erg): If ui::GetXDisplay() ever gets fixed to handle multiple Displays,
+// TODO(erg): If gfx::GetXDisplay() ever gets fixed to handle multiple Displays,
// this must be modified to be per Display instead of a Singleton.
class XSyncHandler {
public:
@@ -85,7 +85,7 @@ class XSyncHandler {
}
void PushPaintCounter(TransportDIB* dib,
- Display* display,
+ XDisplay* display,
Picture picture,
Pixmap pixmap,
const base::Closure& completion_callback);
@@ -96,7 +96,7 @@ class XSyncHandler {
// A struct that has cleanup and callback tasks that were queued into the
// future and are run on |g_backing_store_sync_alarm| firing.
struct BackingStoreEvents {
- BackingStoreEvents(TransportDIB* dib, Display* d, Picture pic, Pixmap pix,
+ BackingStoreEvents(TransportDIB* dib, XDisplay* d, Picture pic, Pixmap pix,
const base::Closure& c)
: dib(dib),
display(d),
@@ -109,7 +109,7 @@ class XSyncHandler {
TransportDIB* dib;
// The display we're running on.
- Display* display;
+ XDisplay* display;
// Data to delete.
Picture picture;
@@ -142,7 +142,7 @@ class XSyncHandler {
};
void XSyncHandler::PushPaintCounter(TransportDIB* dib,
- Display* display,
+ XDisplay* display,
Picture picture,
Pixmap pixmap,
const base::Closure& completion_callback) {
@@ -153,7 +153,7 @@ void XSyncHandler::PushPaintCounter(TransportDIB* dib,
// alarm when it is processed.
XSyncValue value;
XSyncIntToValue(&value, 1);
- XSyncChangeCounter(ui::GetXDisplay(),
+ XSyncChangeCounter(gfx::GetXDisplay(),
backing_store_sync_counter_,
value);
}
@@ -164,7 +164,7 @@ XSyncHandler::XSyncHandler()
xsync_error_base_(0),
backing_store_sync_counter_(0),
backing_store_sync_alarm_(0) {
- Display* display = ui::GetXDisplay();
+ XDisplay* display = gfx::GetXDisplay();
if (XSyncQueryExtension(display,
&xsync_event_base_,
&xsync_error_base_)) {
@@ -191,7 +191,7 @@ XSyncHandler::~XSyncHandler() {
if (loaded_extension_)
gdk_window_remove_filter(NULL, &OnEventThunk, this);
- XSync(ui::GetXDisplay(), False);
+ XSync(gfx::GetXDisplay(), False);
while (!backing_store_events_.empty()) {
// We delete the X11 resources we're holding onto. We don't run the
// callbacks because we are shutting down.
@@ -248,7 +248,7 @@ BackingStoreGtk::BackingStoreGtk(RenderWidgetHost* widget,
void* visual,
int depth)
: BackingStore(widget, size),
- display_(ui::GetXDisplay()),
+ display_(gfx::GetXDisplay()),
shared_memory_support_(ui::QuerySharedMemorySupport(display_)),
use_render_(ui::QueryRenderSupport(display_)),
visual_(visual),
diff --git a/chromium/content/browser/renderer_host/backing_store_gtk.h b/chromium/content/browser/renderer_host/backing_store_gtk.h
index 0e81597c0b6..29776fcdf67 100644
--- a/chromium/content/browser/renderer_host/backing_store_gtk.h
+++ b/chromium/content/browser/renderer_host/backing_store_gtk.h
@@ -12,7 +12,7 @@
#include "build/build_config.h"
#include "content/browser/renderer_host/backing_store.h"
#include "content/common/content_export.h"
-#include "ui/base/x/x11_util.h"
+#include "ui/gfx/x/x11_types.h"
namespace gfx {
class Point;
@@ -39,7 +39,7 @@ class CONTENT_EXPORT BackingStoreGtk : public BackingStore {
virtual ~BackingStoreGtk();
- Display* display() const { return display_; }
+ XDisplay* display() const { return display_; }
XID root_window() const { return root_window_; }
// Copy from the server-side backing store to the target window
@@ -79,7 +79,7 @@ class CONTENT_EXPORT BackingStoreGtk : public BackingStore {
// This is the connection to the X server where this backing store will be
// displayed.
- Display* const display_;
+ XDisplay* const display_;
// What flavor, if any, MIT-SHM (X shared memory) support we have.
const ui::SharedMemorySupport shared_memory_support_;
// If this is true, then we can use Xrender to composite our pixmaps.
diff --git a/chromium/content/browser/renderer_host/backing_store_win.cc b/chromium/content/browser/renderer_host/backing_store_win.cc
index 5ccafbb062b..8e761dd0c32 100644
--- a/chromium/content/browser/renderer_host/backing_store_win.cc
+++ b/chromium/content/browser/renderer_host/backing_store_win.cc
@@ -9,10 +9,10 @@
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/public/common/content_switches.h"
#include "skia/ext/platform_canvas.h"
-#include "ui/base/win/dpi.h"
#include "ui/gfx/gdi_util.h"
#include "ui/gfx/rect_conversions.h"
#include "ui/gfx/size_conversions.h"
+#include "ui/gfx/win/dpi.h"
#include "ui/surface/transport_dib.h"
namespace content {
@@ -92,7 +92,7 @@ bool BackingStoreWin::ColorManagementEnabled() {
size_t BackingStoreWin::MemorySize() {
gfx::Size size_in_pixels = gfx::ToCeiledSize(gfx::ScaleSize(size(),
- ui::win::GetDeviceScaleFactor()));
+ gfx::win::GetDeviceScaleFactor()));
return size_in_pixels.GetArea() * (color_depth_ / 8);
}
@@ -104,6 +104,7 @@ void BackingStoreWin::PaintToBackingStore(
float scale_factor,
const base::Closure& completion_callback,
bool* scheduled_completion_callback) {
+ TRACE_EVENT0("content", "BackingStoreWin::PaintToBackingStore");
*scheduled_completion_callback = false;
gfx::Size size_in_pixels = gfx::ToCeiledSize(gfx::ScaleSize(
size(), scale_factor));
@@ -155,6 +156,7 @@ void BackingStoreWin::PaintToBackingStore(
bool BackingStoreWin::CopyFromBackingStore(const gfx::Rect& rect,
skia::PlatformBitmap* output) {
+ TRACE_EVENT0("content", "BackingStoreWin::CopyFromBackingStore");
// TODO(kevers): Make sure this works with HiDPI backing stores.
if (!output->Allocate(rect.width(), rect.height(), true))
return false;
@@ -168,10 +170,11 @@ bool BackingStoreWin::CopyFromBackingStore(const gfx::Rect& rect,
void BackingStoreWin::ScrollBackingStore(const gfx::Vector2d& delta,
const gfx::Rect& clip_rect,
const gfx::Size& view_size) {
+ TRACE_EVENT0("content", "BackingStoreWin::ScrollBackingStore");
// TODO(darin): this doesn't work if delta x() and y() are both non-zero!
DCHECK(delta.x() == 0 || delta.y() == 0);
- float scale = ui::win::GetDeviceScaleFactor();
+ float scale = gfx::win::GetDeviceScaleFactor();
gfx::Rect screen_rect = gfx::ToEnclosingRect(
gfx::ScaleRect(clip_rect, scale));
int dx = static_cast<int>(delta.x() * scale);
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
index 1bcc8223e97..e4563375681 100644
--- 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
@@ -26,9 +26,9 @@ bool BasicMouseWheelSmoothScrollGesture::ForwardInputEvents(
if (pixels_scrolled_ >= pixels_to_scroll_)
return false;
- double position_delta = smooth_scroll_calculator_.GetScrollDelta(
+ float position_delta = synthetic_gesture_calculator_.GetDelta(
now,
- RenderWidgetHostImpl::From(host)->GetSyntheticScrollMessageInterval());
+ RenderWidgetHostImpl::From(host)->GetSyntheticGestureMessageInterval());
WebKit::WebMouseWheelEvent event;
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
index adea7a30b74..ba127da05bd 100644
--- 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
@@ -6,14 +6,14 @@
#define CONTENT_BROWSER_RENDERER_HOST_BASIC_MOUSE_WHEEL_SMOOTH_SCROLL_GESTURE_
#include "base/time/time.h"
-#include "content/browser/renderer_host/smooth_scroll_calculator.h"
-#include "content/port/browser/smooth_scroll_gesture.h"
+#include "content/browser/renderer_host/synthetic_gesture_calculator.h"
+#include "content/port/browser/synthetic_gesture.h"
namespace content {
class RenderWidgetHost;
-class BasicMouseWheelSmoothScrollGesture : public SmoothScrollGesture {
+class BasicMouseWheelSmoothScrollGesture : public SyntheticGesture {
public:
BasicMouseWheelSmoothScrollGesture(bool scroll_down, int pixels_to_scroll,
int mouse_event_x, int mouse_event_y);
@@ -23,7 +23,7 @@ class BasicMouseWheelSmoothScrollGesture : public SmoothScrollGesture {
private:
virtual ~BasicMouseWheelSmoothScrollGesture();
- SmoothScrollCalculator smooth_scroll_calculator_;
+ SyntheticGestureCalculator synthetic_gesture_calculator_;
bool scroll_down_;
int pixels_scrolled_;
diff --git a/chromium/content/browser/renderer_host/clipboard_message_filter.cc b/chromium/content/browser/renderer_host/clipboard_message_filter.cc
index 0e2426bf224..e681188b937 100644
--- a/chromium/content/browser/renderer_host/clipboard_message_filter.cc
+++ b/chromium/content/browser/renderer_host/clipboard_message_filter.cc
@@ -11,7 +11,6 @@
#include "content/public/browser/browser_context.h"
#include "ipc/ipc_message_macros.h"
#include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/zlib/zlib.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/size.h"
#include "url/gurl.h"
@@ -199,19 +198,9 @@ void ClipboardMessageFilter::OnReadImageReply(
const SkBitmap& bitmap, IPC::Message* reply_msg) {
base::SharedMemoryHandle image_handle = base::SharedMemory::NULLHandle();
uint32 image_size = 0;
- std::string reply_data;
if (!bitmap.isNull()) {
std::vector<unsigned char> png_data;
- SkAutoLockPixels lock(bitmap);
- if (gfx::PNGCodec::EncodeWithCompressionLevel(
- static_cast<const unsigned char*>(bitmap.getPixels()),
- gfx::PNGCodec::FORMAT_BGRA,
- gfx::Size(bitmap.width(), bitmap.height()),
- bitmap.rowBytes(),
- false,
- std::vector<gfx::PNGCodec::Comment>(),
- Z_BEST_SPEED,
- &png_data)) {
+ if (gfx::PNGCodec::FastEncodeBGRASkBitmap(bitmap, false, &png_data)) {
base::SharedMemory buffer;
if (buffer.CreateAndMapAnonymous(png_data.size())) {
memcpy(buffer.memory(), vector_as_array(&png_data), png_data.size());
diff --git a/chromium/content/browser/renderer_host/compositing_iosurface_mac.h b/chromium/content/browser/renderer_host/compositing_iosurface_mac.h
index 674e4e512d6..623272be771 100644
--- a/chromium/content/browser/renderer_host/compositing_iosurface_mac.h
+++ b/chromium/content/browser/renderer_host/compositing_iosurface_mac.h
@@ -19,7 +19,7 @@
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "media/base/video_frame.h"
-#include "ui/base/latency_info.h"
+#include "ui/events/latency_info.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/rect_conversions.h"
diff --git a/chromium/content/browser/renderer_host/compositor_impl_android.cc b/chromium/content/browser/renderer_host/compositor_impl_android.cc
index 53c42e4277a..1e758c35a0d 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android.cc
+++ b/chromium/content/browser/renderer_host/compositor_impl_android.cc
@@ -22,10 +22,13 @@
#include "cc/output/compositor_frame.h"
#include "cc/output/context_provider.h"
#include "cc/output/output_surface.h"
+#include "cc/resources/scoped_ui_resource.h"
+#include "cc/resources/ui_resource_bitmap.h"
#include "cc/trees/layer_tree_host.h"
#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
#include "content/browser/gpu/gpu_surface_tracker.h"
#include "content/common/gpu/client/command_buffer_proxy_impl.h"
+#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/common/gpu/client/gl_helper.h"
#include "content/common/gpu/client/gpu_channel_host.h"
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
@@ -37,6 +40,7 @@
#include "third_party/khronos/GLES2/gl2ext.h"
#include "ui/gfx/android/device_display_info.h"
#include "ui/gfx/android/java_bitmap.h"
+#include "webkit/common/gpu/context_provider_in_process.h"
#include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
namespace gfx {
@@ -48,8 +52,9 @@ namespace {
// Used for drawing directly to the screen. Bypasses resizing and swaps.
class DirectOutputSurface : public cc::OutputSurface {
public:
- DirectOutputSurface(scoped_ptr<WebKit::WebGraphicsContext3D> context3d)
- : cc::OutputSurface(context3d.Pass()) {
+ DirectOutputSurface(
+ const scoped_refptr<cc::ContextProvider>& context_provider)
+ : cc::OutputSurface(context_provider) {
capabilities_.adjust_deadline_for_parent = false;
}
@@ -57,23 +62,26 @@ class DirectOutputSurface : public cc::OutputSurface {
surface_size_ = size;
}
virtual void SwapBuffers(cc::CompositorFrame*) OVERRIDE {
- context3d()->shallowFlushCHROMIUM();
+ context_provider_->Context3d()->shallowFlushCHROMIUM();
}
};
// Used to override capabilities_.adjust_deadline_for_parent to false
class OutputSurfaceWithoutParent : public cc::OutputSurface {
public:
- OutputSurfaceWithoutParent(scoped_ptr<WebKit::WebGraphicsContext3D> context3d)
- : cc::OutputSurface(context3d.Pass()) {
+ OutputSurfaceWithoutParent(
+ const scoped_refptr<
+ content::ContextProviderCommandBuffer>& context_provider)
+ : cc::OutputSurface(context_provider) {
capabilities_.adjust_deadline_for_parent = false;
}
virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE {
- content::WebGraphicsContext3DCommandBufferImpl* command_buffer =
- static_cast<content::WebGraphicsContext3DCommandBufferImpl*>(context3d());
+ content::WebGraphicsContext3DCommandBufferImpl* command_buffer_context =
+ static_cast<content::WebGraphicsContext3DCommandBufferImpl*>(
+ context_provider_->Context3d());
content::CommandBufferProxyImpl* command_buffer_proxy =
- command_buffer->GetCommandBufferProxy();
+ command_buffer_context->GetCommandBufferProxy();
DCHECK(command_buffer_proxy);
command_buffer_proxy->SetLatencyInfo(frame->metadata.latency_info);
@@ -227,10 +235,11 @@ void CompositorImpl::SetSurface(jobject surface) {
void CompositorImpl::SetVisible(bool visible) {
if (!visible) {
+ ui_resource_map_.clear();
host_.reset();
+ client_->UIResourcesAreInvalid();
} else if (!host_) {
cc::LayerTreeSettings settings;
- settings.compositor_name = "BrowserCompositor";
settings.refresh_rate = 60.0;
settings.impl_side_painting = false;
settings.allow_antialiasing = false;
@@ -255,6 +264,9 @@ void CompositorImpl::SetVisible(bool visible) {
host_->SetLayerTreeHostClientReady();
host_->SetViewportSize(size_);
host_->set_has_transparent_background(has_transparent_background_);
+ // Need to recreate the UI resources because a new LayerTreeHost has been
+ // created.
+ client_->DidLoseUIResources();
}
}
@@ -286,6 +298,23 @@ bool CompositorImpl::CompositeAndReadback(void *pixels, const gfx::Rect& rect) {
return false;
}
+cc::UIResourceId CompositorImpl::GenerateUIResource(
+ const cc::UIResourceBitmap& bitmap) {
+ if (!host_)
+ return 0;
+ scoped_ptr<cc::ScopedUIResource> ui_resource =
+ cc::ScopedUIResource::Create(host_.get(), bitmap);
+ cc::UIResourceId id = ui_resource->id();
+ ui_resource_map_.set(id, ui_resource.Pass());
+ return id;
+}
+
+void CompositorImpl::DeleteUIResource(cc::UIResourceId resource_id) {
+ UIResourceMap::iterator it = ui_resource_map_.find(resource_id);
+ if (it != ui_resource_map_.end())
+ ui_resource_map_.erase(it);
+}
+
WebKit::WebGLId CompositorImpl::GenerateTexture(gfx::JavaBitmap& bitmap) {
unsigned int texture_id = BuildBasicTexture();
WebKit::WebGraphicsContext3D* context =
@@ -358,6 +387,41 @@ bool CompositorImpl::CopyTextureToBitmap(WebKit::WebGLId texture_id,
return true;
}
+static scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
+CreateGpuProcessViewContext(
+ const WebKit::WebGraphicsContext3D::Attributes attributes,
+ int surface_id,
+ base::WeakPtr<CompositorImpl> compositor_impl) {
+ GpuChannelHostFactory* factory = BrowserGpuChannelHostFactory::instance();
+ 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();
+}
+
scoped_ptr<cc::OutputSurface> CompositorImpl::CreateOutputSurface(
bool fallback) {
WebKit::WebGraphicsContext3D::Attributes attrs;
@@ -365,46 +429,35 @@ scoped_ptr<cc::OutputSurface> CompositorImpl::CreateOutputSurface(
attrs.noAutomaticFlushes = true;
if (g_use_direct_gl) {
- scoped_ptr<WebKit::WebGraphicsContext3D> context(
- webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl::
- CreateViewContext(attrs, window_));
- if (!window_) {
- return scoped_ptr<cc::OutputSurface>(
- new DirectOutputSurface(context.Pass()));
- }
+ 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();
+ }
- return make_scoped_ptr(new cc::OutputSurface(context.Pass()));
- } else {
- DCHECK(window_ && surface_id_);
- GpuChannelHostFactory* factory = BrowserGpuChannelHostFactory::instance();
- GURL url("chrome://gpu/Compositor::createContext3D");
- scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context(
- new WebGraphicsContext3DCommandBufferImpl(surface_id_,
- url,
- factory,
- weak_factory_.GetWeakPtr()));
- 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(
- attrs,
- 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))) {
- LOG(ERROR) << "Failed to create 3D context for compositor.";
- return scoped_ptr<cc::OutputSurface>();
- }
- return scoped_ptr<cc::OutputSurface>(
- new OutputSurfaceWithoutParent(
- context.PassAs<WebKit::WebGraphicsContext3D>()));
+ DCHECK(window_);
+ DCHECK(surface_id_);
+
+ scoped_refptr<ContextProviderCommandBuffer> context_provider =
+ ContextProviderCommandBuffer::Create(CreateGpuProcessViewContext(
+ attrs, surface_id_, weak_factory_.GetWeakPtr()), "BrowserCompositor");
+ if (!context_provider.get()) {
+ LOG(ERROR) << "Failed to create 3D context for compositor.";
+ return scoped_ptr<cc::OutputSurface>();
}
+
+ return scoped_ptr<cc::OutputSurface>(
+ new OutputSurfaceWithoutParent(context_provider));
}
void CompositorImpl::OnLostResources() {
diff --git a/chromium/content/browser/renderer_host/compositor_impl_android.h b/chromium/content/browser/renderer_host/compositor_impl_android.h
index 845e830aad4..58e44c89449 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android.h
+++ b/chromium/content/browser/renderer_host/compositor_impl_android.h
@@ -7,8 +7,10 @@
#include "base/basictypes.h"
#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 "content/browser/renderer_host/image_transport_factory_android.h"
#include "content/common/content_export.h"
@@ -21,6 +23,7 @@ namespace cc {
class InputHandlerClient;
class Layer;
class LayerTreeHost;
+class ScopedUIResource;
}
namespace content {
@@ -60,6 +63,9 @@ class CONTENT_EXPORT CompositorImpl
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(
gfx::Size& size, int data_size, void* data) OVERRIDE;
@@ -117,6 +123,10 @@ class CONTENT_EXPORT CompositorImpl
scoped_refptr<cc::ContextProvider> null_offscreen_context_provider_;
+ typedef base::ScopedPtrHashMap<cc::UIResourceId, cc::ScopedUIResource>
+ UIResourceMap;
+ UIResourceMap ui_resource_map_;
+
DISALLOW_COPY_AND_ASSIGN(CompositorImpl);
};
diff --git a/chromium/content/browser/renderer_host/frame_memory_manager.cc b/chromium/content/browser/renderer_host/frame_memory_manager.cc
new file mode 100644
index 00000000000..708bddfa61b
--- /dev/null
+++ b/chromium/content/browser/renderer_host/frame_memory_manager.cc
@@ -0,0 +1,66 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/frame_memory_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();
+}
+
+void FrameMemoryManager::AddFrame(FrameContainer* frame, bool visible) {
+ RemoveFrame(frame);
+ if (visible)
+ visible_frames_.insert(frame);
+ else
+ hidden_frames_.push_front(frame);
+ CullHiddenFrames();
+}
+
+void FrameMemoryManager::RemoveFrame(FrameContainer* frame) {
+ visible_frames_.erase(frame);
+ hidden_frames_.remove(frame);
+}
+
+void FrameMemoryManager::SetFrameVisibility(FrameContainer* frame,
+ bool visible) {
+ if (visible) {
+ hidden_frames_.remove(frame);
+ visible_frames_.insert(frame);
+ } else {
+ visible_frames_.erase(frame);
+ hidden_frames_.push_front(frame);
+ CullHiddenFrames();
+ }
+}
+
+FrameMemoryManager::FrameMemoryManager() {}
+
+FrameMemoryManager::~FrameMemoryManager() {}
+
+void FrameMemoryManager::CullHiddenFrames() {
+ while (!hidden_frames_.empty() &&
+ hidden_frames_.size() + visible_frames_.size() >
+ MaxNumberOfSavedFrames()) {
+ size_t old_size = hidden_frames_.size();
+ // Should remove self from list.
+ hidden_frames_.back()->ReleaseCurrentFrame();
+ DCHECK_EQ(hidden_frames_.size() + 1, old_size);
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/frame_memory_manager.h b/chromium/content/browser/renderer_host/frame_memory_manager.h
new file mode 100644
index 00000000000..ce3fc258226
--- /dev/null
+++ b/chromium/content/browser/renderer_host/frame_memory_manager.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_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
new file mode 100644
index 00000000000..74080cd408c
--- /dev/null
+++ b/chromium/content/browser/renderer_host/generic_touch_gesture_android.cc
@@ -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.
+
+#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
new file mode 100644
index 00000000000..030239b1c30
--- /dev/null
+++ b/chromium/content/browser/renderer_host/generic_touch_gesture_android.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_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/gtk_im_context_wrapper.cc b/chromium/content/browser/renderer_host/gtk_im_context_wrapper.cc
index 55d2e76bb30..65dc54524c2 100644
--- a/chromium/content/browser/renderer_host/gtk_im_context_wrapper.cc
+++ b/chromium/content/browser/renderer_host/gtk_im_context_wrapper.cc
@@ -439,7 +439,7 @@ void GtkIMContextWrapper::ProcessInputMethodResult(const GdkEventKey* event,
// Unlike a Char event, an IME event is NOT dispatched to onkeypress()
// handlers or autofill.
host->ImeConfirmComposition(
- commit_text_,ui::Range::InvalidRange(),false);
+ commit_text_,gfx::Range::InvalidRange(),false);
// Set this flag to false, as this composition session has been
// finished.
is_composing_text_ = false;
@@ -477,7 +477,7 @@ void GtkIMContextWrapper::ConfirmComposition() {
if (host_view_->GetRenderWidgetHost()) {
RenderWidgetHostImpl::From(
host_view_->GetRenderWidgetHost())->ImeConfirmComposition(
- string16(), ui::Range::InvalidRange(), false);
+ string16(), gfx::Range::InvalidRange(), false);
}
// Reset the input method.
@@ -503,7 +503,7 @@ void GtkIMContextWrapper::HandleCommit(const string16& text) {
SendFakeCompositionKeyEvent(WebKit::WebInputEvent::RawKeyDown);
RenderWidgetHostImpl::From(
host_view_->GetRenderWidgetHost())->ImeConfirmComposition(
- text, ui::Range::InvalidRange(), false);
+ text, gfx::Range::InvalidRange(), false);
SendFakeCompositionKeyEvent(WebKit::WebInputEvent::KeyUp);
}
}
@@ -532,7 +532,7 @@ void GtkIMContextWrapper::HandlePreeditChanged(const gchar* text,
// TODO(suzhe): due to a bug of webkit, we currently can't use selection range
// with composition string. See: https://bugs.webkit.org/show_bug.cgi?id=40805
- composition_.selection = ui::Range(cursor_position);
+ composition_.selection = gfx::Range(cursor_position);
// In case we are using a buggy input method which doesn't fire
// "preedit_start" signal.
diff --git a/chromium/content/browser/renderer_host/gtk_plugin_container_manager.cc b/chromium/content/browser/renderer_host/gtk_plugin_container_manager.cc
index 93e20778607..861491111b5 100644
--- a/chromium/content/browser/renderer_host/gtk_plugin_container_manager.cc
+++ b/chromium/content/browser/renderer_host/gtk_plugin_container_manager.cc
@@ -9,7 +9,7 @@
#include "base/logging.h"
#include "content/browser/renderer_host/gtk_plugin_container.h"
#include "content/common/webplugin_geometry.h"
-#include "ui/base/gtk/gtk_compat.h"
+#include "ui/gfx/gtk_compat.h"
#include "ui/gfx/gtk_util.h"
namespace content {
diff --git a/chromium/content/browser/renderer_host/gtk_window_utils.cc b/chromium/content/browser/renderer_host/gtk_window_utils.cc
index 979c58d05a5..f05cdca3b66 100644
--- a/chromium/content/browser/renderer_host/gtk_window_utils.cc
+++ b/chromium/content/browser/renderer_host/gtk_window_utils.cc
@@ -10,10 +10,11 @@
#include <vector>
-#include "ui/base/gtk/gtk_compat.h"
+#include "third_party/WebKit/public/web/WebScreenInfo.h"
#include "ui/base/x/x11_util.h"
+#include "ui/gfx/gtk_compat.h"
#include "ui/gfx/rect.h"
-#include "third_party/WebKit/public/web/WebScreenInfo.h"
+#include "ui/gfx/x/x11_types.h"
namespace content {
@@ -44,7 +45,7 @@ gfx::Rect GetWorkArea(Window window) {
property[start_index + 2], property[start_index + 3]);
}
-WebKit::WebScreenInfo GetScreenInfo(Display* display, int screenNumber) {
+WebKit::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.
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 39071c9bec3..bc0d365d249 100644
--- a/chromium/content/browser/renderer_host/image_transport_factory_android.cc
+++ b/chromium/content/browser/renderer_host/image_transport_factory_android.cc
@@ -128,7 +128,9 @@ CmdBufferImageTransportFactory::CmdBufferImageTransportFactory() {
64 * 1024, // starting buffer size
64 * 1024, // min buffer size
std::min(3 * full_screen_texture_size_in_bytes,
- kDefaultMaxTransferBufferSize));
+ kDefaultMaxTransferBufferSize),
+ WebGraphicsContext3DCommandBufferImpl::kNoLimit
+ );
if (context_->makeContextCurrent())
context_->pushGroupMarkerEXT(
diff --git a/chromium/content/browser/renderer_host/ime_adapter_android.cc b/chromium/content/browser/renderer_host/ime_adapter_android.cc
index 588c5ada8e6..da14d7a3d5d 100644
--- a/chromium/content/browser/renderer_host/ime_adapter_android.cc
+++ b/chromium/content/browser/renderer_host/ime_adapter_android.cc
@@ -174,7 +174,7 @@ void ImeAdapterAndroid::CommitText(JNIEnv* env, jobject, jstring text) {
return;
string16 text16 = ConvertJavaStringToUTF16(env, text);
- rwhi->ImeConfirmComposition(text16, ui::Range::InvalidRange(), false);
+ rwhi->ImeConfirmComposition(text16, gfx::Range::InvalidRange(), false);
}
void ImeAdapterAndroid::FinishComposingText(JNIEnv* env, jobject) {
@@ -182,7 +182,7 @@ void ImeAdapterAndroid::FinishComposingText(JNIEnv* env, jobject) {
if (!rwhi)
return;
- rwhi->ImeConfirmComposition(string16(), ui::Range::InvalidRange(), true);
+ rwhi->ImeConfirmComposition(string16(), gfx::Range::InvalidRange(), true);
}
void ImeAdapterAndroid::AttachImeAdapter(JNIEnv* env, jobject java_object) {
diff --git a/chromium/content/browser/renderer_host/input/OWNERS b/chromium/content/browser/renderer_host/input/OWNERS
index 4dabaf0da2c..4893edbdf02 100644
--- a/chromium/content/browser/renderer_host/input/OWNERS
+++ b/chromium/content/browser/renderer_host/input/OWNERS
@@ -1,2 +1,3 @@
-nduca@chromium.org
aelias@chromium.org
+jdduke@chromium.org
+nduca@chromium.org
diff --git a/chromium/content/browser/renderer_host/input/browser_input_event.cc b/chromium/content/browser/renderer_host/input/browser_input_event.cc
new file mode 100644
index 00000000000..276245e3526
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/browser_input_event.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/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
new file mode 100644
index 00000000000..6022d80ecd2
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/browser_input_event.h
@@ -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.
+
+#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
new file mode 100644
index 00000000000..97b565311d5
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/buffered_input_router.cc
@@ -0,0 +1,336 @@
+// Copyright 2013 The Chromium Authors. All rights 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
new file mode 100644
index 00000000000..a9802a68198
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/buffered_input_router.h
@@ -0,0 +1,144 @@
+// Copyright 2013 The Chromium Authors. All 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
new file mode 100644
index 00000000000..4d63444fef8
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/buffered_input_router_unittest.cc
@@ -0,0 +1,320 @@
+// Copyright 2013 The Chromium Authors. 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/immediate_input_router.cc b/chromium/content/browser/renderer_host/input/immediate_input_router.cc
index 96e8bb9ac44..a4c69054fd1 100644
--- a/chromium/content/browser/renderer_host/input/immediate_input_router.cc
+++ b/chromium/content/browser/renderer_host/input/immediate_input_router.cc
@@ -7,6 +7,7 @@
#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"
@@ -20,8 +21,8 @@
#include "content/public/browser/notification_types.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/common/content_switches.h"
-#include "ui/base/events/event.h"
-#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/events/event.h"
+#include "ui/events/keycodes/keyboard_codes.h"
using base::Time;
using base::TimeDelta;
@@ -71,12 +72,13 @@ const char* GetEventAckName(InputEventAckState ack_result) {
} // namespace
-ImmediateInputRouter::ImmediateInputRouter(
- RenderProcessHost* process,
- InputRouterClient* client,
- int routing_id)
+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),
@@ -85,6 +87,9 @@ ImmediateInputRouter::ImmediateInputRouter(
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);
}
@@ -92,20 +97,23 @@ ImmediateInputRouter::ImmediateInputRouter(
ImmediateInputRouter::~ImmediateInputRouter() {
}
-bool ImmediateInputRouter::SendInput(IPC::Message* message) {
+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);
- scoped_ptr<IPC::Message> scoped_message(message);
- switch (scoped_message->type()) {
+ switch (message->type()) {
// Check for types that require an ACK.
case InputMsg_SelectRange::ID:
- return SendSelectRange(scoped_message.release());
+ return SendSelectRange(message.Pass());
case InputMsg_MoveCaret::ID:
- return SendMoveCaret(scoped_message.release());
+ return SendMoveCaret(message.Pass());
case InputMsg_HandleInputEvent::ID:
NOTREACHED() << "WebInputEvents should never be sent via SendInput.";
return false;
default:
- return Send(scoped_message.release());
+ return Send(message.release());
}
}
@@ -199,6 +207,7 @@ void ImmediateInputRouter::SendKeyboardEvent(
void ImmediateInputRouter::SendGestureEvent(
const GestureEventWithLatencyInfo& gesture_event) {
+ HandleGestureScroll(gesture_event);
if (!client_->OnSendGestureEvent(gesture_event))
return;
FilterAndSendWebInputEvent(gesture_event.event, gesture_event.latency, false);
@@ -252,6 +261,7 @@ void ImmediateInputRouter::SendTouchEventImmediately(
void ImmediateInputRouter::SendGestureEventImmediately(
const GestureEventWithLatencyInfo& gesture_event) {
+ HandleGestureScroll(gesture_event);
if (!client_->OnSendGestureEventImmediately(gesture_event))
return;
FilterAndSendWebInputEvent(gesture_event.event, gesture_event.latency, false);
@@ -277,10 +287,6 @@ bool ImmediateInputRouter::ShouldForwardGestureEvent(
return gesture_event_filter_->ShouldForward(touch_event);
}
-bool ImmediateInputRouter::HasQueuedGestureEvents() const {
- return gesture_event_filter_->HasQueuedGestureEvents();
-}
-
bool ImmediateInputRouter::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
bool message_is_ok = true;
@@ -294,7 +300,7 @@ bool ImmediateInputRouter::OnMessageReceived(const IPC::Message& message) {
IPC_END_MESSAGE_MAP()
if (!message_is_ok)
- client_->OnUnexpectedEventAck(true);
+ ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE);
return handled;
}
@@ -302,29 +308,29 @@ bool ImmediateInputRouter::OnMessageReceived(const IPC::Message& message) {
void ImmediateInputRouter::OnTouchEventAck(
const TouchEventWithLatencyInfo& event,
InputEventAckState ack_result) {
- client_->OnTouchEventAck(event, ack_result);
+ ack_handler_->OnTouchEventAck(event, ack_result);
}
-bool ImmediateInputRouter::SendSelectRange(IPC::Message* message) {
+bool ImmediateInputRouter::SendSelectRange(scoped_ptr<IPC::Message> message) {
DCHECK(message->type() == InputMsg_SelectRange::ID);
if (select_range_pending_) {
- next_selection_range_.reset(message);
+ next_selection_range_ = message.Pass();
return true;
}
select_range_pending_ = true;
- return Send(message);
+ return Send(message.release());
}
-bool ImmediateInputRouter::SendMoveCaret(IPC::Message* message) {
+bool ImmediateInputRouter::SendMoveCaret(scoped_ptr<IPC::Message> message) {
DCHECK(message->type() == InputMsg_MoveCaret::ID);
if (move_caret_pending_) {
- next_move_caret_.reset(message);
+ next_move_caret_ = message.Pass();
return true;
}
move_caret_pending_ = true;
- return Send(message);
+ return Send(message.release());
}
bool ImmediateInputRouter::Send(IPC::Message* message) {
@@ -398,7 +404,7 @@ void ImmediateInputRouter::FilterAndSendWebInputEvent(
// 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
@@ -434,13 +440,13 @@ void ImmediateInputRouter::OnInputEventAck(
void ImmediateInputRouter::OnMsgMoveCaretAck() {
move_caret_pending_ = false;
if (next_move_caret_)
- SendMoveCaret(next_move_caret_.release());
+ SendMoveCaret(next_move_caret_.Pass());
}
void ImmediateInputRouter::OnSelectRangeAck() {
select_range_pending_ = false;
if (next_selection_range_)
- SendSelectRange(next_selection_range_.release());
+ SendSelectRange(next_selection_range_.Pass());
}
void ImmediateInputRouter::OnHasTouchEventHandlers(bool has_handlers) {
@@ -461,7 +467,7 @@ void ImmediateInputRouter::ProcessInputEventAck(
int type = static_cast<int>(event_type);
if (type < WebInputEvent::Undefined) {
- client_->OnUnexpectedEventAck(true);
+ ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE);
} else if (type == WebInputEvent::MouseMove) {
mouse_move_pending_ = false;
@@ -501,23 +507,17 @@ void ImmediateInputRouter::ProcessKeyboardAck(
int type,
InputEventAckState ack_result) {
if (key_queue_.empty()) {
- LOG(ERROR) << "Got a KeyEvent back from the renderer but we "
- << "don't seem to have sent it to the renderer!";
+ ack_handler_->OnUnexpectedEventAck(InputAckHandler::UNEXPECTED_ACK);
} else if (key_queue_.front().type != type) {
- LOG(ERROR) << "We seem to have a different key type sent from "
- << "the renderer. (" << key_queue_.front().type << " vs. "
- << type << "). Ignoring event.";
-
// Something must be wrong. Clear the |key_queue_| and char event
// suppression so that we can resume from the error.
key_queue_.clear();
- client_->OnUnexpectedEventAck(false);
+ ack_handler_->OnUnexpectedEventAck(InputAckHandler::UNEXPECTED_EVENT_TYPE);
} else {
NativeWebKeyboardEvent front_item = key_queue_.front();
key_queue_.pop_front();
- client_->OnKeyboardEventAck(front_item, ack_result);
-
+ 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).
@@ -530,7 +530,7 @@ void ImmediateInputRouter::ProcessWheelAck(InputEventAckState ack_result) {
// Process the unhandled wheel event here before calling
// ForwardWheelEventWithLatencyInfo() since it will mutate
// current_wheel_event_.
- client_->OnWheelEventAck(current_wheel_event_.event, ack_result);
+ ack_handler_->OnWheelEventAck(current_wheel_event_.event, ack_result);
// Now send the next (coalesced) mouse wheel event.
if (!coalesced_mouse_wheel_events_.empty()) {
@@ -544,7 +544,7 @@ void ImmediateInputRouter::ProcessWheelAck(InputEventAckState ack_result) {
void ImmediateInputRouter::ProcessGestureAck(int type,
InputEventAckState ack_result) {
const bool processed = (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result);
- client_->OnGestureEventAck(
+ ack_handler_->OnGestureEventAck(
gesture_event_filter_->GetGestureEventAwaitingAck(), ack_result);
gesture_event_filter_->ProcessGestureAck(processed, type);
}
@@ -556,4 +556,19 @@ void ImmediateInputRouter::ProcessTouchAck(
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.h b/chromium/content/browser/renderer_host/input/immediate_input_router.h
index 270ca3dc67e..1d1a0c0e168 100644
--- a/chromium/content/browser/renderer_host/input/immediate_input_router.h
+++ b/chromium/content/browser/renderer_host/input/immediate_input_router.h
@@ -21,6 +21,7 @@ struct LatencyInfo;
namespace content {
class GestureEventFilter;
+class InputAckHandler;
class InputRouterClient;
class RenderProcessHost;
class RenderWidgetHostImpl;
@@ -33,11 +34,13 @@ class CONTENT_EXPORT ImmediateInputRouter
public:
ImmediateInputRouter(RenderProcessHost* process,
InputRouterClient* client,
+ InputAckHandler* ack_handler,
int routing_id);
virtual ~ImmediateInputRouter();
// InputRouter
- virtual bool SendInput(IPC::Message* message) OVERRIDE;
+ virtual void Flush() OVERRIDE;
+ virtual bool SendInput(scoped_ptr<IPC::Message> message) OVERRIDE;
virtual void SendMouseEvent(
const MouseEventWithLatencyInfo& mouse_event) OVERRIDE;
virtual void SendWheelEvent(
@@ -59,7 +62,6 @@ class CONTENT_EXPORT ImmediateInputRouter
virtual bool ShouldForwardTouchEvent() const OVERRIDE;
virtual bool ShouldForwardGestureEvent(
const GestureEventWithLatencyInfo& gesture_event) const OVERRIDE;
- virtual bool HasQueuedGestureEvents() const OVERRIDE;
// IPC::Listener
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
@@ -73,12 +75,14 @@ class CONTENT_EXPORT ImmediateInputRouter
}
private:
+ friend class ImmediateInputRouterTest;
+
// TouchEventQueueClient
virtual void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
InputEventAckState ack_result) OVERRIDE;
- bool SendMoveCaret(IPC::Message* message);
- bool SendSelectRange(IPC::Message* message);
+ 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
@@ -127,11 +131,15 @@ private:
void ProcessTouchAck(InputEventAckState ack_result,
const ui::LatencyInfo& latency_info);
+ void HandleGestureScroll(
+ const GestureEventWithLatencyInfo& gesture_event);
+
int routing_id() const { return routing_id_; }
RenderProcessHost* process_;
InputRouterClient* client_;
+ InputAckHandler* ack_handler_;
int routing_id_;
// (Similar to |mouse_move_pending_|.) True while waiting for SelectRange_ACK.
@@ -186,6 +194,10 @@ 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_;
+
scoped_ptr<TouchEventQueue> touch_event_queue_;
scoped_ptr<GestureEventFilter> gesture_event_filter_;
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
index ed725ee1a10..0e4767a3239 100644
--- a/chromium/content/browser/renderer_host/input/immediate_input_router_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/immediate_input_router_unittest.cc
@@ -8,6 +8,8 @@
#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"
@@ -15,11 +17,11 @@
#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/base/keycodes/keyboard_codes.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/base/events/event.h"
+#include "ui/events/event.h"
#endif
using base::TimeDelta;
@@ -100,266 +102,22 @@ bool EventListIsSubset(const ScopedVector<ui::TouchEvent>& subset,
} // namespace
-class MockInputRouterClient : public InputRouterClient {
+class ImmediateInputRouterTest : public InputRouterTest {
public:
- MockInputRouterClient()
- : input_router_(NULL),
- in_flight_event_count_(0),
- has_touch_handler_(false),
- ack_count_(0),
- unexpected_event_ack_called_(false),
- ack_state_(INPUT_EVENT_ACK_STATE_UNKNOWN),
- filter_state_(INPUT_EVENT_ACK_STATE_NOT_CONSUMED),
- is_shortcut_(false),
- allow_send_key_event_(true),
- send_called_(false),
- send_immediately_called_(false) {
- }
- virtual ~MockInputRouterClient() {
- }
-
- // InputRouterClient
- virtual InputEventAckState FilterInputEvent(
- const WebInputEvent& input_event,
- const ui::LatencyInfo& latency_info) OVERRIDE {
- return filter_state_;
- }
-
- // Called each time a WebInputEvent IPC is sent.
- virtual void IncrementInFlightEventCount() OVERRIDE {
- ++in_flight_event_count_;
- }
-
- // Called each time a WebInputEvent ACK IPC is received.
- virtual void DecrementInFlightEventCount() OVERRIDE {
- --in_flight_event_count_;
- }
-
- // Called when the renderer notifies that it has touch event handlers.
- virtual void OnHasTouchEventHandlers(bool has_handlers) OVERRIDE {
- has_touch_handler_ = has_handlers;
- }
-
- virtual bool OnSendKeyboardEvent(
- const NativeWebKeyboardEvent& key_event,
- const ui::LatencyInfo& latency_info,
- bool* is_shortcut) OVERRIDE {
- send_called_ = true;
- sent_key_event_ = key_event;
- *is_shortcut = is_shortcut_;
-
- return allow_send_key_event_;
- }
-
- virtual bool OnSendWheelEvent(
- const MouseWheelEventWithLatencyInfo& wheel_event) OVERRIDE {
- send_called_ = true;
- sent_wheel_event_ = wheel_event;
-
- return true;
- }
-
- virtual bool OnSendMouseEvent(
- const MouseEventWithLatencyInfo& mouse_event) OVERRIDE {
- send_called_ = true;
- sent_mouse_event_ = mouse_event;
-
- return true;
- }
-
- virtual bool OnSendTouchEvent(
- const TouchEventWithLatencyInfo& touch_event) OVERRIDE {
- send_called_ = true;
- sent_touch_event_ = touch_event;
-
- return true;
- }
-
- virtual bool OnSendGestureEvent(
- const GestureEventWithLatencyInfo& gesture_event) OVERRIDE {
- send_called_ = true;
- sent_gesture_event_ = gesture_event;
-
- return input_router_->ShouldForwardGestureEvent(gesture_event);
- }
-
- virtual bool OnSendMouseEventImmediately(
- const MouseEventWithLatencyInfo& mouse_event) OVERRIDE {
- send_immediately_called_ = true;
- immediately_sent_mouse_event_ = mouse_event;
-
- return true;
- }
-
- virtual bool OnSendTouchEventImmediately(
- const TouchEventWithLatencyInfo& touch_event) OVERRIDE {
- send_immediately_called_ = true;
- immediately_sent_touch_event_ = touch_event;
-
- return true;
- }
-
- virtual bool OnSendGestureEventImmediately(
- const GestureEventWithLatencyInfo& gesture_event) OVERRIDE {
- send_immediately_called_ = true;
- immediately_sent_gesture_event_ = gesture_event;
-
- return true;
- }
-
- // Called upon event ack receipt from the renderer.
- virtual void OnKeyboardEventAck(const NativeWebKeyboardEvent& event,
- InputEventAckState ack_result) OVERRIDE {
- VLOG(1) << __FUNCTION__ << " called!";
- acked_key_event_ = event;
- RecordAckCalled(ack_result);
- }
- virtual void OnWheelEventAck(const WebMouseWheelEvent& event,
- InputEventAckState ack_result) OVERRIDE {
- VLOG(1) << __FUNCTION__ << " called!";
- acked_wheel_event_ = event;
- RecordAckCalled(ack_result);
- }
- virtual void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
- InputEventAckState ack_result) OVERRIDE {
- VLOG(1) << __FUNCTION__ << " called!";
- acked_touch_event_ = event;
- RecordAckCalled(ack_result);
- }
- virtual void OnGestureEventAck(const WebGestureEvent& event,
- InputEventAckState ack_result) OVERRIDE {
- VLOG(1) << __FUNCTION__ << " called!";
- RecordAckCalled(ack_result);
- }
- virtual void OnUnexpectedEventAck(bool bad_message) OVERRIDE {
- VLOG(1) << __FUNCTION__ << " called!";
- unexpected_event_ack_called_ = true;
- }
-
- void ExpectSendCalled(bool called) {
- EXPECT_EQ(called, send_called_);
- send_called_ = false;
- }
- void ExpectSendImmediatelyCalled(bool called) {
- EXPECT_EQ(called, send_immediately_called_);
- send_immediately_called_ = false;
- }
- void ExpectAckCalled(int times) {
- EXPECT_EQ(times, ack_count_);
- ack_count_ = 0;
- }
-
- void set_input_router(InputRouter* input_router) {
- input_router_ = input_router;
- }
- bool has_touch_handler() const { return has_touch_handler_; }
- InputEventAckState ack_state() const { return ack_state_; }
- void set_filter_state(InputEventAckState filter_state) {
- filter_state_ = filter_state;
- }
- bool unexpected_event_ack_called() const {
- return unexpected_event_ack_called_;
- }
- const NativeWebKeyboardEvent& acked_keyboard_event() {
- return acked_key_event_;
- }
- const WebMouseWheelEvent& acked_wheel_event() {
- return acked_wheel_event_;
- }
- const TouchEventWithLatencyInfo& acked_touch_event() {
- return acked_touch_event_;
- }
- void set_is_shortcut(bool is_shortcut) {
- is_shortcut_ = is_shortcut;
- }
- void set_allow_send_key_event(bool allow) {
- allow_send_key_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_;
- }
-
- private:
- void RecordAckCalled(InputEventAckState ack_result) {
- ++ack_count_;
- ack_state_ = ack_result;
- }
-
- InputRouter* input_router_;
- int in_flight_event_count_;
- bool has_touch_handler_;
-
- int ack_count_;
- bool unexpected_event_ack_called_;
- InputEventAckState ack_state_;
- InputEventAckState filter_state_;
- NativeWebKeyboardEvent acked_key_event_;
- WebMouseWheelEvent acked_wheel_event_;
- TouchEventWithLatencyInfo acked_touch_event_;
-
- bool is_shortcut_;
- bool allow_send_key_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_;
-};
-
-class ImmediateInputRouterTest : public testing::Test {
- public:
- ImmediateInputRouterTest() {
- }
- virtual ~ImmediateInputRouterTest() {
- }
+ ImmediateInputRouterTest() {}
+ virtual ~ImmediateInputRouterTest() {}
protected:
- // testing::Test
- virtual void SetUp() {
- browser_context_.reset(new TestBrowserContext());
- process_.reset(new MockRenderProcessHost(browser_context_.get()));
- client_.reset(new MockInputRouterClient());
- input_router_.reset(new ImmediateInputRouter(
- process_.get(),
- client_.get(),
- MSG_ROUTING_NONE));
- client_->set_input_router(input_router_.get());
- }
- virtual void TearDown() {
- // Process all pending tasks to avoid leaks.
- base::MessageLoop::current()->RunUntilIdle();
-
- input_router_.reset();
- client_.reset();
- process_.reset();
- browser_context_.reset();
+ // 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(WebInputEvent::Type type,
+ void SendInputEventACK(WebKit::WebInputEvent::Type type,
InputEventAckState ack_result) {
scoped_ptr<IPC::Message> response(
new InputHostMsg_HandleInputEvent_ACK(0, type, ack_result,
@@ -367,177 +125,16 @@ class ImmediateInputRouterTest : public testing::Test {
input_router_->OnMessageReceived(*response);
}
- void 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 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 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);
- client_->ExpectSendImmediatelyCalled(true);
- EXPECT_EQ(mouse_event.type, client_->sent_mouse_event().event.type);
- EXPECT_EQ(x, client_->sent_mouse_event().event.x);
- EXPECT_EQ(mouse_event.type,
- client_->immediately_sent_mouse_event().event.type);
- EXPECT_EQ(x, client_->immediately_sent_mouse_event().event.x);
- }
-
- void 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 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 SimulateGestureEvent(WebInputEvent::Type type,
- WebGestureEvent::SourceDevice sourceDevice) {
- WebGestureEvent gesture_event;
- SimulateGestureEventCore(type, sourceDevice, &gesture_event);
- }
-
- 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);
- }
-
- 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);
- }
-
- // Inject synthetic GestureFlingStart events.
- void 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);
- }
-
- // Set the timestamp for the touch-event.
- void 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 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 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 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 ReleaseTouchPoint(int index) {
- CHECK(index >= 0 && index < touch_event_.touchesLengthCap);
- touch_event_.touches[index].state = WebTouchPoint::StateReleased;
- touch_event_.type = WebInputEvent::TouchEnd;
+ 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;
+ 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;
+ input_router()->gesture_event_filter()->maximum_tap_gap_time_ms_ = delay_ms;
}
size_t TouchEventQueueSize() {
@@ -548,8 +145,16 @@ class ImmediateInputRouterTest : public testing::Test {
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();
+ return input_router()->touch_event_queue();
}
unsigned GestureEventLastQueueEventSize() {
@@ -590,18 +195,8 @@ class ImmediateInputRouterTest : public testing::Test {
}
GestureEventFilter* gesture_event_filter() const {
- return input_router_->gesture_event_filter();
+ return input_router()->gesture_event_filter();
}
-
- scoped_ptr<MockRenderProcessHost> process_;
- scoped_ptr<MockInputRouterClient> client_;
- scoped_ptr<ImmediateInputRouter> input_router_;
-
- private:
- base::MessageLoopForUI message_loop_;
- WebTouchEvent touch_event_;
-
- scoped_ptr<TestBrowserContext> browser_context_;
};
#if GTEST_HAS_PARAM_TEST
@@ -613,8 +208,8 @@ class ImmediateInputRouterWithSourceTest
#endif // GTEST_HAS_PARAM_TEST
TEST_F(ImmediateInputRouterTest, CoalescesRangeSelection) {
- input_router_->SendInput(
- new InputMsg_SelectRange(0, gfx::Point(1, 2), gfx::Point(3, 4)));
+ 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),
@@ -623,12 +218,12 @@ TEST_F(ImmediateInputRouterTest, CoalescesRangeSelection) {
process_->sink().ClearMessages();
// Send two more messages without acking.
- input_router_->SendInput(
- new InputMsg_SelectRange(0, gfx::Point(5, 6), gfx::Point(7, 8)));
+ 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(
- new InputMsg_SelectRange(0, gfx::Point(9, 10), gfx::Point(11, 12)));
+ 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.
@@ -654,17 +249,20 @@ TEST_F(ImmediateInputRouterTest, CoalescesRangeSelection) {
}
TEST_F(ImmediateInputRouterTest, CoalescesCaretMove) {
- input_router_->SendInput(new InputMsg_MoveCaret(0, gfx::Point(1, 2)));
+ 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(new InputMsg_MoveCaret(0, gfx::Point(5, 6)));
+ 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(new InputMsg_MoveCaret(0, gfx::Point(9, 10)));
+ 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.
@@ -697,7 +295,7 @@ TEST_F(ImmediateInputRouterTest, HandledInputEvent) {
EXPECT_EQ(0u, process_->sink().message_count());
// OnKeyboardEventAck should be triggered without actual ack.
- client_->ExpectAckCalled(1);
+ ack_handler_->ExpectAckCalled(1);
// As the event was acked already, keyboard event queue should be
// empty.
@@ -705,14 +303,14 @@ TEST_F(ImmediateInputRouterTest, HandledInputEvent) {
}
TEST_F(ImmediateInputRouterTest, ClientCanceledKeyboardEvent) {
- client_->set_allow_send_key_event(false);
+ 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());
- client_->ExpectAckCalled(0);
+ ack_handler_->ExpectAckCalled(0);
}
TEST_F(ImmediateInputRouterTest, ShortcutKeyboardEvent) {
@@ -734,7 +332,7 @@ TEST_F(ImmediateInputRouterTest, NoncorrespondingKeyEvents) {
SendInputEventACK(WebInputEvent::KeyUp,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_TRUE(client_->unexpected_event_ack_called());
+ EXPECT_TRUE(ack_handler_->unexpected_event_ack_called());
}
// Tests ported from RenderWidgetHostTest --------------------------------------
@@ -754,8 +352,9 @@ TEST_F(ImmediateInputRouterTest, HandleKeyEventsWeSent) {
// Send the simulated response from the renderer back.
SendInputEventACK(WebInputEvent::RawKeyDown,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- client_->ExpectAckCalled(1);
- EXPECT_EQ(WebInputEvent::RawKeyDown, client_->acked_keyboard_event().type);
+ ack_handler_->ExpectAckCalled(1);
+ EXPECT_EQ(WebInputEvent::RawKeyDown,
+ ack_handler_->acked_keyboard_event().type);
}
TEST_F(ImmediateInputRouterTest, IgnoreKeyEventsWeDidntSend) {
@@ -763,7 +362,7 @@ TEST_F(ImmediateInputRouterTest, IgnoreKeyEventsWeDidntSend) {
SendInputEventACK(WebInputEvent::RawKeyDown,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- client_->ExpectAckCalled(0);
+ ack_handler_->ExpectAckCalled(0);
}
TEST_F(ImmediateInputRouterTest, CoalescesWheelEvents) {
@@ -786,7 +385,7 @@ TEST_F(ImmediateInputRouterTest, CoalescesWheelEvents) {
// so that additional input events can be processed before
// we turn off coalescing.
base::MessageLoop::current()->RunUntilIdle();
- client_->ExpectAckCalled(1);
+ ack_handler_->ExpectAckCalled(1);
EXPECT_EQ(1U, process_->sink().message_count());
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
InputMsg_HandleInputEvent::ID));
@@ -796,7 +395,7 @@ TEST_F(ImmediateInputRouterTest, CoalescesWheelEvents) {
SendInputEventACK(WebInputEvent::MouseWheel,
INPUT_EVENT_ACK_STATE_CONSUMED);
base::MessageLoop::current()->RunUntilIdle();
- client_->ExpectAckCalled(1);
+ ack_handler_->ExpectAckCalled(1);
EXPECT_EQ(1U, process_->sink().message_count());
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
InputMsg_HandleInputEvent::ID));
@@ -806,7 +405,7 @@ TEST_F(ImmediateInputRouterTest, CoalescesWheelEvents) {
SendInputEventACK(WebInputEvent::MouseWheel,
INPUT_EVENT_ACK_STATE_CONSUMED);
base::MessageLoop::current()->RunUntilIdle();
- client_->ExpectAckCalled(1);
+ ack_handler_->ExpectAckCalled(1);
EXPECT_EQ(0U, process_->sink().message_count());
// FIXME(kouhei): Below is testing gesture event filter. Maybe separate test?
@@ -909,7 +508,7 @@ TEST_F(ImmediateInputRouterTest, CoalescesScrollGestureEvents) {
SendInputEventACK(WebInputEvent::GestureScrollBegin,
INPUT_EVENT_ACK_STATE_CONSUMED);
base::MessageLoop::current()->RunUntilIdle();
- client_->ExpectAckCalled(1);
+ ack_handler_->ExpectAckCalled(1);
EXPECT_EQ(1U, process_->sink().message_count());
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
InputMsg_HandleInputEvent::ID));
@@ -919,7 +518,7 @@ TEST_F(ImmediateInputRouterTest, CoalescesScrollGestureEvents) {
SendInputEventACK(WebInputEvent::GestureScrollUpdate,
INPUT_EVENT_ACK_STATE_CONSUMED);
base::MessageLoop::current()->RunUntilIdle();
- client_->ExpectAckCalled(1);
+ ack_handler_->ExpectAckCalled(1);
EXPECT_EQ(1U, process_->sink().message_count());
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
InputMsg_HandleInputEvent::ID));
@@ -929,7 +528,7 @@ TEST_F(ImmediateInputRouterTest, CoalescesScrollGestureEvents) {
SendInputEventACK(WebInputEvent::GestureScrollUpdate,
INPUT_EVENT_ACK_STATE_CONSUMED);
base::MessageLoop::current()->RunUntilIdle();
- client_->ExpectAckCalled(1);
+ ack_handler_->ExpectAckCalled(1);
EXPECT_EQ(1U, process_->sink().message_count());
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
InputMsg_HandleInputEvent::ID));
@@ -939,7 +538,7 @@ TEST_F(ImmediateInputRouterTest, CoalescesScrollGestureEvents) {
SendInputEventACK(WebInputEvent::GestureScrollEnd,
INPUT_EVENT_ACK_STATE_CONSUMED);
base::MessageLoop::current()->RunUntilIdle();
- client_->ExpectAckCalled(1);
+ ack_handler_->ExpectAckCalled(1);
EXPECT_EQ(0U, process_->sink().message_count());
}
@@ -1192,14 +791,14 @@ TEST_P(ImmediateInputRouterWithSourceTest, GestureFlingCancelsFiltered) {
SendInputEventACK(WebInputEvent::GestureFlingStart,
INPUT_EVENT_ACK_STATE_CONSUMED);
base::MessageLoop::current()->RunUntilIdle();
- client_->ExpectAckCalled(1);
+ 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();
- client_->ExpectAckCalled(1);
+ ack_handler_->ExpectAckCalled(1);
EXPECT_EQ(0U, GestureEventLastQueueEventSize());
// GFC before previous GFS is acked.
@@ -1218,7 +817,7 @@ TEST_P(ImmediateInputRouterWithSourceTest, GestureFlingCancelsFiltered) {
SendInputEventACK(WebInputEvent::GestureFlingCancel,
INPUT_EVENT_ACK_STATE_CONSUMED);
base::MessageLoop::current()->RunUntilIdle();
- client_->ExpectAckCalled(2);
+ ack_handler_->ExpectAckCalled(2);
EXPECT_EQ(0U, GestureEventLastQueueEventSize());
// GFS is added to the queue if another event is pending
@@ -1563,18 +1162,18 @@ TEST_F(ImmediateInputRouterTest, TouchEventQueue) {
SendInputEventACK(WebInputEvent::TouchStart,
INPUT_EVENT_ACK_STATE_CONSUMED);
EXPECT_EQ(1U, TouchEventQueueSize());
- client_->ExpectAckCalled(1);
+ ack_handler_->ExpectAckCalled(1);
EXPECT_EQ(WebInputEvent::TouchStart,
- client_->acked_touch_event().event.type);
+ 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());
- client_->ExpectAckCalled(1);
+ ack_handler_->ExpectAckCalled(1);
EXPECT_EQ(WebInputEvent::TouchMove,
- client_->acked_touch_event().event.type);
+ ack_handler_->acked_touch_event().event.type);
EXPECT_EQ(0U, process_->sink().message_count());
}
@@ -1615,8 +1214,8 @@ TEST_F(ImmediateInputRouterTest, TouchEventQueueFlush) {
INPUT_EVENT_ACK_STATE_CONSUMED);
EXPECT_EQ(31U, TouchEventQueueSize());
EXPECT_EQ(WebInputEvent::TouchStart,
- client_->acked_touch_event().event.type);
- client_->ExpectAckCalled(1);
+ ack_handler_->acked_touch_event().event.type);
+ ack_handler_->ExpectAckCalled(1);
EXPECT_EQ(1U, process_->sink().message_count());
process_->sink().ClearMessages();
@@ -1663,8 +1262,8 @@ TEST_F(ImmediateInputRouterTest, TouchEventQueueCoalesce) {
EXPECT_EQ(1U, process_->sink().message_count());
EXPECT_EQ(2U, TouchEventQueueSize());
EXPECT_EQ(WebInputEvent::TouchStart,
- client_->acked_touch_event().event.type);
- client_->ExpectAckCalled(1);
+ ack_handler_->acked_touch_event().event.type);
+ ack_handler_->ExpectAckCalled(1);
process_->sink().ClearMessages();
// Coalesced touch-move events should be sent.
@@ -1678,8 +1277,8 @@ TEST_F(ImmediateInputRouterTest, TouchEventQueueCoalesce) {
EXPECT_EQ(1U, process_->sink().message_count());
EXPECT_EQ(1U, TouchEventQueueSize());
EXPECT_EQ(WebInputEvent::TouchMove,
- client_->acked_touch_event().event.type);
- client_->ExpectAckCalled(10);
+ ack_handler_->acked_touch_event().event.type);
+ ack_handler_->ExpectAckCalled(10);
process_->sink().ClearMessages();
// ACK the release.
@@ -1688,8 +1287,8 @@ TEST_F(ImmediateInputRouterTest, TouchEventQueueCoalesce) {
EXPECT_EQ(0U, process_->sink().message_count());
EXPECT_EQ(0U, TouchEventQueueSize());
EXPECT_EQ(WebInputEvent::TouchEnd,
- client_->acked_touch_event().event.type);
- client_->ExpectAckCalled(1);
+ 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
@@ -1844,8 +1443,8 @@ TEST_F(ImmediateInputRouterTest, TouchEventQueueNoConsumer) {
INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
EXPECT_EQ(0U, TouchEventQueueSize());
EXPECT_EQ(WebInputEvent::TouchMove,
- client_->acked_touch_event().event.type);
- client_->ExpectAckCalled(2);
+ ack_handler_->acked_touch_event().event.type);
+ ack_handler_->ExpectAckCalled(2);
EXPECT_EQ(0U, process_->sink().message_count());
process_->sink().ClearMessages();
@@ -1854,8 +1453,8 @@ TEST_F(ImmediateInputRouterTest, TouchEventQueueNoConsumer) {
SendTouchEvent();
EXPECT_EQ(0U, process_->sink().message_count());
EXPECT_EQ(WebInputEvent::TouchEnd,
- client_->acked_touch_event().event.type);
- client_->ExpectAckCalled(1);
+ 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
@@ -1883,8 +1482,9 @@ TEST_F(ImmediateInputRouterTest, TouchEventQueueNoConsumer) {
SendInputEventACK(WebInputEvent::TouchStart,
INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(WebInputEvent::TouchEnd, client_->acked_touch_event().event.type);
- client_->ExpectAckCalled(4);
+ EXPECT_EQ(WebInputEvent::TouchEnd,
+ ack_handler_->acked_touch_event().event.type);
+ ack_handler_->ExpectAckCalled(4);
EXPECT_EQ(1U, TouchEventQueueSize());
process_->sink().ClearMessages();
@@ -1892,8 +1492,9 @@ TEST_F(ImmediateInputRouterTest, TouchEventQueueNoConsumer) {
SendInputEventACK(WebInputEvent::TouchStart,
INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(WebInputEvent::TouchStart, client_->acked_touch_event().event.type);
- client_->ExpectAckCalled(1);
+ 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,
@@ -2030,7 +1631,7 @@ TEST_F(ImmediateInputRouterTest, TouchEventQueueConsumerIgnoreMultiFinger) {
EXPECT_EQ(1U, process_->sink().message_count());
EXPECT_EQ(2U, TouchEventQueueSize());
EXPECT_EQ(WebInputEvent::TouchMove,
- client_->acked_touch_event().event.type);
+ ack_handler_->acked_touch_event().event.type);
process_->sink().ClearMessages();
// ACK the press with NO_CONSUMED_EXISTS. This should release the queued
@@ -2040,7 +1641,7 @@ TEST_F(ImmediateInputRouterTest, TouchEventQueueConsumerIgnoreMultiFinger) {
EXPECT_EQ(0U, process_->sink().message_count());
EXPECT_EQ(0U, TouchEventQueueSize());
EXPECT_EQ(WebInputEvent::TouchMove,
- client_->acked_touch_event().event.type);
+ ack_handler_->acked_touch_event().event.type);
ReleaseTouchPoint(2);
ReleaseTouchPoint(1);
@@ -2118,11 +1719,11 @@ TEST_F(ImmediateInputRouterTest, AckedTouchEventState) {
for (size_t i = 0; i < arraysize(acks); ++i) {
SendInputEventACK(acks[i],
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(acks[i], client_->acked_touch_event().event.type);
+ EXPECT_EQ(acks[i], ack_handler_->acked_touch_event().event.type);
ScopedVector<ui::TouchEvent> acked;
MakeUITouchEventsFromWebTouchEvents(
- client_->acked_touch_event(), &acked, coordinate_system);
+ ack_handler_->acked_touch_event(), &acked, coordinate_system);
bool success = EventListIsSubset(acked, expected_events);
EXPECT_TRUE(success) << "Failed on step: " << i;
if (!success)
@@ -2151,9 +1752,9 @@ TEST_F(ImmediateInputRouterTest, UnhandledWheelEvent) {
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
// Check that the correct unhandled wheel event was received.
- client_->ExpectAckCalled(1);
- EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, client_->ack_state());
- EXPECT_EQ(client_->acked_wheel_event().deltaY, -5);
+ 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());
@@ -2162,7 +1763,96 @@ TEST_F(ImmediateInputRouterTest, UnhandledWheelEvent) {
process_->sink().ClearMessages();
// Check that the correct unhandled wheel event was received.
- EXPECT_EQ(client_->acked_wheel_event().deltaY, -5);
+ 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
new file mode 100644
index 00000000000..3e09b07cd03
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/input_ack_handler.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_INPUT_INPUT_ACK_HANDLER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_ACK_HANDLER_H_
+
+#include "base/basictypes.h"
+#include "content/port/browser/event_with_latency_info.h"
+#include "content/port/common/input_event_ack_state.h"
+#include "content/public/browser/native_web_keyboard_event.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+
+namespace content {
+
+// Provided customized ack response for input events.
+class CONTENT_EXPORT InputAckHandler {
+ public:
+ virtual ~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,
+ InputEventAckState ack_result) = 0;
+ virtual void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
+ InputEventAckState ack_result) = 0;
+ virtual void OnGestureEventAck(const WebKit::WebGestureEvent& event,
+ InputEventAckState ack_result) = 0;
+
+ enum UnexpectedEventAckType {
+ UNEXPECTED_ACK,
+ UNEXPECTED_EVENT_TYPE,
+ BAD_ACK_MESSAGE
+ };
+ virtual void OnUnexpectedEventAck(UnexpectedEventAckType type) = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_ACK_HANDLER_H_
diff --git a/chromium/content/browser/renderer_host/input/input_queue.cc b/chromium/content/browser/renderer_host/input/input_queue.cc
new file mode 100644
index 00000000000..c10500b9c08
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/input_queue.cc
@@ -0,0 +1,183 @@
+// Copyright 2013 The Chromium Authors. All rights 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
new file mode 100644
index 00000000000..2c7acb707d2
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/input_queue.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_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
new file mode 100644
index 00000000000..f1151d92fed
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/input_queue_client.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_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
new file mode 100644
index 00000000000..2d183d96cca
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/input_queue_unittest.cc
@@ -0,0 +1,363 @@
+// Copyright 2013 The Chromium Authors. 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 2d8a4c6dd5d..5e4533fc1dd 100644
--- a/chromium/content/browser/renderer_host/input/input_router.h
+++ b/chromium/content/browser/renderer_host/input/input_router.h
@@ -24,10 +24,14 @@ class InputRouter : public IPC::Listener {
public:
virtual ~InputRouter() {}
+ // Should be called only in response to |SetNeedsFlush| requests made via
+ // the |InputRouterClient|.
+ virtual void Flush() = 0;
+
// Send and take ownership of the the given InputMsg_*. This should be used
// only for event types not associated with a WebInputEvent. Returns true on
// success and false otherwise.
- virtual bool SendInput(IPC::Message* message) = 0;
+ virtual bool SendInput(scoped_ptr<IPC::Message> message) = 0;
// WebInputEvents
virtual void SendMouseEvent(
@@ -60,9 +64,6 @@ class InputRouter : public IPC::Listener {
// |gesture_event| to the router.
virtual bool ShouldForwardGestureEvent(
const GestureEventWithLatencyInfo& gesture_event) const = 0;
-
- // Returns |true| if the router has any queued or in-flight gesture events.
- virtual bool HasQueuedGestureEvents() const = 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 9c854224b52..6479332d444 100644
--- a/chromium/content/browser/renderer_host/input/input_router_client.h
+++ b/chromium/content/browser/renderer_host/input/input_router_client.h
@@ -61,16 +61,15 @@ class CONTENT_EXPORT InputRouterClient {
virtual bool OnSendGestureEventImmediately(
const GestureEventWithLatencyInfo& gesture_event) = 0;
- // 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,
- InputEventAckState ack_result) = 0;
- virtual void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
- InputEventAckState ack_result) = 0;
- virtual void OnGestureEventAck(const WebKit::WebGestureEvent& event,
- InputEventAckState ack_result) = 0;
- virtual void OnUnexpectedEventAck(bool bad_message) = 0;
+ // Certain router implementations require periodic flushing of queued events.
+ // When this method is called, the client should ensure a timely call, either
+ // synchronous or asynchronous, of |Flush| on the InputRouter.
+ virtual void SetNeedsFlush() = 0;
+
+ // Called when the router has finished flushing all events queued at the time
+ // of the call to Flush. The call will typically be asynchronous with
+ // respect to the call to |Flush| on the InputRouter.
+ virtual void DidFlush() = 0;
};
} // 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
new file mode 100644
index 00000000000..da1ef1efb70
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/input_router_unittest.cc
@@ -0,0 +1,225 @@
+// Copyright 2013 The Chromium Authors. All rights 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
new file mode 100644
index 00000000000..20a68af3fb1
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/input_router_unittest.h
@@ -0,0 +1,83 @@
+// Copyright 2013 The Chromium Authors. All 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
new file mode 100644
index 00000000000..fc97ab3450b
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/mock_input_ack_handler.cc
@@ -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.
+
+#include "content/browser/renderer_host/input/mock_input_ack_handler.h"
+
+#include "content/browser/renderer_host/input/input_router.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;
+
+namespace content {
+
+MockInputAckHandler::MockInputAckHandler()
+ : input_router_(NULL),
+ ack_count_(0),
+ unexpected_event_ack_called_(false),
+ ack_state_(INPUT_EVENT_ACK_STATE_UNKNOWN) {}
+
+MockInputAckHandler::~MockInputAckHandler() {}
+
+void MockInputAckHandler::OnKeyboardEventAck(
+ const NativeWebKeyboardEvent& event,
+ InputEventAckState ack_result) {
+ VLOG(1) << __FUNCTION__ << " called!";
+ acked_key_event_ = event;
+ RecordAckCalled(ack_result);
+}
+
+void MockInputAckHandler::OnWheelEventAck(
+ const WebMouseWheelEvent& event,
+ InputEventAckState ack_result) {
+ VLOG(1) << __FUNCTION__ << " called!";
+ acked_wheel_event_ = event;
+ RecordAckCalled(ack_result);
+}
+
+void MockInputAckHandler::OnTouchEventAck(
+ const TouchEventWithLatencyInfo& event,
+ InputEventAckState ack_result) {
+ VLOG(1) << __FUNCTION__ << " called!";
+ acked_touch_event_ = event;
+ RecordAckCalled(ack_result);
+ if (touch_followup_event_)
+ input_router_->SendGestureEvent(*touch_followup_event_);
+}
+
+void MockInputAckHandler::OnGestureEventAck(
+ const WebGestureEvent& event,
+ InputEventAckState ack_result) {
+ VLOG(1) << __FUNCTION__ << " called!";
+ acked_gesture_event_ = event;
+ RecordAckCalled(ack_result);
+}
+
+void MockInputAckHandler::OnUnexpectedEventAck(UnexpectedEventAckType type) {
+ VLOG(1) << __FUNCTION__ << " called!";
+ unexpected_event_ack_called_ = true;
+}
+
+void MockInputAckHandler::ExpectAckCalled(int times) {
+ EXPECT_EQ(times, ack_count_);
+ ack_count_ = 0;
+}
+
+void MockInputAckHandler::RecordAckCalled(InputEventAckState ack_result) {
+ ++ack_count_;
+ ack_state_ = ack_result;
+}
+
+} // namespace content
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
new file mode 100644
index 00000000000..604b26b94cb
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/mock_input_ack_handler.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_RENDERER_HOST_INPUT_MOCK_INPUT_ACK_HANDLER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_MOCK_INPUT_ACK_HANDLER_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/renderer_host/input/input_ack_handler.h"
+
+namespace content {
+
+class InputRouter;
+
+class MockInputAckHandler : public InputAckHandler {
+ public:
+ MockInputAckHandler();
+ virtual ~MockInputAckHandler();
+
+ // InputAckHandler
+ virtual void OnKeyboardEventAck(const NativeWebKeyboardEvent& event,
+ InputEventAckState ack_result) OVERRIDE;
+ virtual void OnWheelEventAck(const WebKit::WebMouseWheelEvent& event,
+ InputEventAckState ack_result) OVERRIDE;
+ virtual void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
+ InputEventAckState ack_result) OVERRIDE;
+ virtual void OnGestureEventAck(const WebKit::WebGestureEvent& event,
+ InputEventAckState ack_result) OVERRIDE;
+ virtual void OnUnexpectedEventAck(UnexpectedEventAckType type) OVERRIDE;
+
+ void ExpectAckCalled(int times);
+
+ void set_input_router(InputRouter* input_router) {
+ input_router_ = input_router;
+ }
+
+ void set_followup_touch_event(scoped_ptr<GestureEventWithLatencyInfo> event) {
+ touch_followup_event_ = event.Pass();
+ }
+
+ bool unexpected_event_ack_called() const {
+ return unexpected_event_ack_called_;
+ }
+ InputEventAckState ack_state() const { return ack_state_; }
+
+ const NativeWebKeyboardEvent& acked_keyboard_event() const {
+ return acked_key_event_;
+ }
+ const WebKit::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 {
+ return acked_gesture_event_;
+ }
+
+ private:
+ void RecordAckCalled(InputEventAckState ack_result);
+
+ InputRouter* input_router_;
+
+ int ack_count_;
+ bool unexpected_event_ack_called_;
+ InputEventAckState ack_state_;
+ NativeWebKeyboardEvent acked_key_event_;
+ WebKit::WebMouseWheelEvent acked_wheel_event_;
+ TouchEventWithLatencyInfo acked_touch_event_;
+ WebKit::WebGestureEvent acked_gesture_event_;
+
+ scoped_ptr<GestureEventWithLatencyInfo> touch_followup_event_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_MOCK_INPUT_ACK_HANDLER_H_
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
new file mode 100644
index 00000000000..86fb53b6b58
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/mock_input_router_client.cc
@@ -0,0 +1,148 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/mock_input_router_client.h"
+
+#include "content/browser/renderer_host/input/input_router.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;
+
+namespace content {
+
+MockInputRouterClient::MockInputRouterClient()
+ : input_router_(NULL),
+ 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),
+ did_flush_called_(false),
+ set_needs_flush_called_(false) {}
+
+MockInputRouterClient::~MockInputRouterClient() {}
+
+InputEventAckState MockInputRouterClient::FilterInputEvent(
+ const WebInputEvent& input_event,
+ const ui::LatencyInfo& latency_info) {
+ return filter_state_;
+}
+
+void MockInputRouterClient::IncrementInFlightEventCount() {
+ ++in_flight_event_count_;
+}
+
+void MockInputRouterClient::DecrementInFlightEventCount() {
+ --in_flight_event_count_;
+}
+
+void MockInputRouterClient::OnHasTouchEventHandlers(
+ bool has_handlers) {
+ 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;
+}
+
+void MockInputRouterClient::ExpectDidFlushCalled(bool called) {
+ EXPECT_EQ(called, did_flush_called_);
+ did_flush_called_ = false;
+}
+
+void MockInputRouterClient::DidFlush() {
+ did_flush_called_ = true;
+}
+
+void MockInputRouterClient::SetNeedsFlush() {
+ set_needs_flush_called_ = true;
+}
+
+} // namespace content
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
new file mode 100644
index 00000000000..a02f73891f0
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/mock_input_router_client.h
@@ -0,0 +1,126 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_MOCK_INPUT_ROUTER_CLIENT_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_MOCK_INPUT_ROUTER_CLIENT_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/renderer_host/input/input_router_client.h"
+
+namespace content {
+
+class InputRouter;
+
+class MockInputRouterClient : public InputRouterClient {
+ public:
+ MockInputRouterClient();
+ virtual ~MockInputRouterClient();
+
+ // InputRouterClient
+ virtual InputEventAckState FilterInputEvent(
+ const WebKit::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 void DidFlush() OVERRIDE;
+ virtual void SetNeedsFlush() OVERRIDE;
+
+ void ExpectSendCalled(bool called);
+ void ExpectSendImmediatelyCalled(bool called);
+ void ExpectNeedsFlushCalled(bool called);
+ void ExpectDidFlushCalled(bool called);
+
+ void set_input_router(InputRouter* input_router) {
+ input_router_ = input_router;
+ }
+
+ bool has_touch_handler() const { return has_touch_handler_; }
+ void set_filter_state(InputEventAckState filter_state) {
+ filter_state_ = filter_state;
+ }
+ 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_;
+ }
+
+ 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_;
+ int in_flight_event_count_;
+ bool has_touch_handler_;
+
+ 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 did_flush_called_;
+ bool set_needs_flush_called_;
+ scoped_ptr<GestureEventWithLatencyInfo> touch_followup_event_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_MOCK_INPUT_ROUTER_CLIENT_H_
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 c1675b9952d..e22c05d0f80 100644
--- a/chromium/content/browser/renderer_host/input/touch_event_queue.cc
+++ b/chromium/content/browser/renderer_host/input/touch_event_queue.cc
@@ -91,7 +91,8 @@ class CoalescedWebTouchEvent {
TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client)
: client_(client),
- dispatching_touch_ack_(false) {
+ dispatching_touch_ack_(false),
+ no_touch_move_to_renderer_(false) {
DCHECK(client);
}
@@ -212,6 +213,10 @@ bool TouchEventQueue::ShouldForwardToRenderer(
if (event.type == WebKit::WebInputEvent::TouchStart)
return true;
+ if (event.type == WebKit::WebInputEvent::TouchMove &&
+ no_touch_move_to_renderer_)
+ return false;
+
for (unsigned int i = 0; i < event.touchesLength; ++i) {
const WebKit::WebTouchPoint& point = event.touches[i];
// If a point has been stationary, then don't take it into account.
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 23dda66c38b..358fae9c50d 100644
--- a/chromium/content/browser/renderer_host/input/touch_event_queue.h
+++ b/chromium/content/browser/renderer_host/input/touch_event_queue.h
@@ -61,6 +61,10 @@ class TouchEventQueue {
return touch_queue_.empty();
}
+ void set_no_touch_move_to_renderer(bool value) {
+ no_touch_move_to_renderer_ = value;
+ }
+
private:
friend class MockRenderWidgetHost;
friend class ImmediateInputRouterTest;
@@ -88,6 +92,11 @@ class TouchEventQueue {
// Used to defer touch forwarding when ack dispatch triggers |QueueEvent()|.
bool dispatching_touch_ack_;
+ // 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_;
+
DISALLOW_COPY_AND_ASSIGN(TouchEventQueue);
};
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 eca820bb28b..b5c96c657eb 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
@@ -7,8 +7,8 @@
#include "base/logging.h"
#include "content/browser/renderer_host/input/web_input_event_util.h"
#include "content/browser/renderer_host/input/web_input_event_util_posix.h"
-#include "ui/base/keycodes/keyboard_code_conversion_android.h"
-#include "ui/base/keycodes/keyboard_codes_posix.h"
+#include "ui/events/keycodes/keyboard_code_conversion_android.h"
+#include "ui/events/keycodes/keyboard_codes_posix.h"
namespace content {
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
new file mode 100644
index 00000000000..c101595c79f
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_gtk.cc
@@ -0,0 +1,603 @@
+// Copyright 2013 The Chromium Authors. All rights 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/web_input_event_builders_gtk.h"
+
+#include <gdk/gdk.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+
+#include "base/logging.h"
+#include "content/browser/renderer_host/input/web_input_event_util_posix.h"
+#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;
+
+namespace {
+
+// For click count tracking.
+static int num_clicks = 0;
+static GdkWindow* last_click_event_window = 0;
+static gint last_click_time = 0;
+static gint last_click_x = 0;
+static gint last_click_y = 0;
+static WebMouseEvent::Button last_click_button = WebMouseEvent::ButtonNone;
+
+bool ShouldForgetPreviousClick(GdkWindow* window, gint time, gint x, gint y) {
+ static GtkSettings* settings = gtk_settings_get_default();
+
+ if (window != last_click_event_window)
+ return true;
+
+ gint double_click_time = 250;
+ gint double_click_distance = 5;
+ g_object_get(G_OBJECT(settings),
+ "gtk-double-click-time",
+ &double_click_time,
+ "gtk-double-click-distance",
+ &double_click_distance,
+ NULL);
+ return (time - last_click_time) > double_click_time ||
+ std::abs(x - last_click_x) > double_click_distance ||
+ std::abs(y - last_click_y) > double_click_distance;
+}
+
+void ResetClickCountState() {
+ num_clicks = 0;
+ last_click_event_window = 0;
+ last_click_time = 0;
+ last_click_x = 0;
+ last_click_y = 0;
+ last_click_button = WebKit::WebMouseEvent::ButtonNone;
+}
+
+bool IsKeyPadKeyval(guint keyval) {
+ // Keypad keyvals all fall into one range.
+ return keyval >= GDK_KP_Space && keyval <= GDK_KP_9;
+}
+
+double GdkEventTimeToWebEventTime(guint32 time) {
+ // Convert from time in ms to time in sec.
+ return time / 1000.0;
+}
+
+int GdkStateToWebEventModifiers(guint state) {
+ int modifiers = 0;
+ if (state & GDK_SHIFT_MASK)
+ modifiers |= WebInputEvent::ShiftKey;
+ if (state & GDK_CONTROL_MASK)
+ modifiers |= WebInputEvent::ControlKey;
+ if (state & GDK_MOD1_MASK)
+ modifiers |= WebInputEvent::AltKey;
+ if (state & GDK_META_MASK)
+ modifiers |= WebInputEvent::MetaKey;
+ if (state & GDK_BUTTON1_MASK)
+ modifiers |= WebInputEvent::LeftButtonDown;
+ if (state & GDK_BUTTON2_MASK)
+ modifiers |= WebInputEvent::MiddleButtonDown;
+ if (state & GDK_BUTTON3_MASK)
+ modifiers |= WebInputEvent::RightButtonDown;
+ if (state & GDK_LOCK_MASK)
+ modifiers |= WebInputEvent::CapsLockOn;
+ if (state & GDK_MOD2_MASK)
+ modifiers |= WebInputEvent::NumLockOn;
+ return modifiers;
+}
+
+ui::KeyboardCode GdkEventToWindowsKeyCode(const GdkEventKey* event) {
+ static const unsigned int kHardwareCodeToGDKKeyval[] = {
+ 0, // 0x00:
+ 0, // 0x01:
+ 0, // 0x02:
+ 0, // 0x03:
+ 0, // 0x04:
+ 0, // 0x05:
+ 0, // 0x06:
+ 0, // 0x07:
+ 0, // 0x08:
+ 0, // 0x09: GDK_Escape
+ GDK_1, // 0x0A: GDK_1
+ GDK_2, // 0x0B: GDK_2
+ GDK_3, // 0x0C: GDK_3
+ GDK_4, // 0x0D: GDK_4
+ GDK_5, // 0x0E: GDK_5
+ GDK_6, // 0x0F: GDK_6
+ GDK_7, // 0x10: GDK_7
+ GDK_8, // 0x11: GDK_8
+ GDK_9, // 0x12: GDK_9
+ GDK_0, // 0x13: GDK_0
+ GDK_minus, // 0x14: GDK_minus
+ GDK_equal, // 0x15: GDK_equal
+ 0, // 0x16: GDK_BackSpace
+ 0, // 0x17: GDK_Tab
+ GDK_q, // 0x18: GDK_q
+ GDK_w, // 0x19: GDK_w
+ GDK_e, // 0x1A: GDK_e
+ GDK_r, // 0x1B: GDK_r
+ GDK_t, // 0x1C: GDK_t
+ GDK_y, // 0x1D: GDK_y
+ GDK_u, // 0x1E: GDK_u
+ GDK_i, // 0x1F: GDK_i
+ GDK_o, // 0x20: GDK_o
+ GDK_p, // 0x21: GDK_p
+ GDK_bracketleft, // 0x22: GDK_bracketleft
+ GDK_bracketright, // 0x23: GDK_bracketright
+ 0, // 0x24: GDK_Return
+ 0, // 0x25: GDK_Control_L
+ GDK_a, // 0x26: GDK_a
+ GDK_s, // 0x27: GDK_s
+ GDK_d, // 0x28: GDK_d
+ GDK_f, // 0x29: GDK_f
+ GDK_g, // 0x2A: GDK_g
+ GDK_h, // 0x2B: GDK_h
+ GDK_j, // 0x2C: GDK_j
+ GDK_k, // 0x2D: GDK_k
+ GDK_l, // 0x2E: GDK_l
+ GDK_semicolon, // 0x2F: GDK_semicolon
+ GDK_apostrophe, // 0x30: GDK_apostrophe
+ GDK_grave, // 0x31: GDK_grave
+ 0, // 0x32: GDK_Shift_L
+ GDK_backslash, // 0x33: GDK_backslash
+ GDK_z, // 0x34: GDK_z
+ GDK_x, // 0x35: GDK_x
+ GDK_c, // 0x36: GDK_c
+ GDK_v, // 0x37: GDK_v
+ GDK_b, // 0x38: GDK_b
+ GDK_n, // 0x39: GDK_n
+ GDK_m, // 0x3A: GDK_m
+ GDK_comma, // 0x3B: GDK_comma
+ GDK_period, // 0x3C: GDK_period
+ GDK_slash, // 0x3D: GDK_slash
+ 0, // 0x3E: GDK_Shift_R
+ 0, // 0x3F:
+ 0, // 0x40:
+ 0, // 0x41:
+ 0, // 0x42:
+ 0, // 0x43:
+ 0, // 0x44:
+ 0, // 0x45:
+ 0, // 0x46:
+ 0, // 0x47:
+ 0, // 0x48:
+ 0, // 0x49:
+ 0, // 0x4A:
+ 0, // 0x4B:
+ 0, // 0x4C:
+ 0, // 0x4D:
+ 0, // 0x4E:
+ 0, // 0x4F:
+ 0, // 0x50:
+ 0, // 0x51:
+ 0, // 0x52:
+ 0, // 0x53:
+ 0, // 0x54:
+ 0, // 0x55:
+ 0, // 0x56:
+ 0, // 0x57:
+ 0, // 0x58:
+ 0, // 0x59:
+ 0, // 0x5A:
+ 0, // 0x5B:
+ 0, // 0x5C:
+ 0, // 0x5D:
+ 0, // 0x5E:
+ 0, // 0x5F:
+ 0, // 0x60:
+ 0, // 0x61:
+ 0, // 0x62:
+ 0, // 0x63:
+ 0, // 0x64:
+ 0, // 0x65:
+ 0, // 0x66:
+ 0, // 0x67:
+ 0, // 0x68:
+ 0, // 0x69:
+ 0, // 0x6A:
+ 0, // 0x6B:
+ 0, // 0x6C:
+ 0, // 0x6D:
+ 0, // 0x6E:
+ 0, // 0x6F:
+ 0, // 0x70:
+ 0, // 0x71:
+ 0, // 0x72:
+ GDK_Super_L, // 0x73: GDK_Super_L
+ GDK_Super_R, // 0x74: GDK_Super_R
+ };
+
+ // |windows_key_code| has to include a valid virtual-key code even when we
+ // use non-US layouts, e.g. even when we type an 'A' key of a US keyboard
+ // on the Hebrew layout, |windows_key_code| should be VK_A.
+ // On the other hand, |event->keyval| value depends on the current
+ // GdkKeymap object, i.e. when we type an 'A' key of a US keyboard on
+ // the Hebrew layout, |event->keyval| becomes GDK_hebrew_shin and this
+ // ui::WindowsKeyCodeForGdkKeyCode() call returns 0.
+ // To improve compatibilty with Windows, we use |event->hardware_keycode|
+ // for retrieving its Windows key-code for the keys when the
+ // WebCore::windows_key_codeForEvent() call returns 0.
+ // We shouldn't use |event->hardware_keycode| for keys that GdkKeymap
+ // objects cannot change because |event->hardware_keycode| doesn't change
+ // even when we change the layout options, e.g. when we swap a control
+ // key and a caps-lock key, GTK doesn't swap their
+ // |event->hardware_keycode| values but swap their |event->keyval| values.
+ ui::KeyboardCode windows_key_code =
+ ui::WindowsKeyCodeForGdkKeyCode(event->keyval);
+ if (windows_key_code)
+ return windows_key_code;
+
+ if (event->hardware_keycode < arraysize(kHardwareCodeToGDKKeyval)) {
+ int keyval = kHardwareCodeToGDKKeyval[event->hardware_keycode];
+ if (keyval)
+ return ui::WindowsKeyCodeForGdkKeyCode(keyval);
+ }
+
+ // This key is one that keyboard-layout drivers cannot change.
+ // Use |event->keyval| to retrieve its |windows_key_code| value.
+ return ui::WindowsKeyCodeForGdkKeyCode(event->keyval);
+}
+
+// Normalizes event->state to make it Windows/Mac compatible. Since the way
+// of setting modifier mask on X is very different than Windows/Mac as shown
+// in http://crbug.com/127142#c8, the normalization is necessary.
+guint NormalizeEventState(const GdkEventKey* event) {
+ guint mask = 0;
+ switch (GdkEventToWindowsKeyCode(event)) {
+ case ui::VKEY_CONTROL:
+ case ui::VKEY_LCONTROL:
+ case ui::VKEY_RCONTROL:
+ mask = GDK_CONTROL_MASK;
+ break;
+ case ui::VKEY_SHIFT:
+ case ui::VKEY_LSHIFT:
+ case ui::VKEY_RSHIFT:
+ mask = GDK_SHIFT_MASK;
+ break;
+ case ui::VKEY_MENU:
+ case ui::VKEY_LMENU:
+ case ui::VKEY_RMENU:
+ mask = GDK_MOD1_MASK;
+ break;
+ case ui::VKEY_CAPITAL:
+ mask = GDK_LOCK_MASK;
+ break;
+ default:
+ return event->state;
+ }
+ if (event->type == GDK_KEY_PRESS)
+ return event->state | mask;
+ return event->state & ~mask;
+}
+
+// Gets the corresponding control character of a specified key code. See:
+// http://en.wikipedia.org/wiki/Control_characters
+// We emulate Windows behavior here.
+int GetControlCharacter(ui::KeyboardCode 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
+ return windows_key_code - ui::VKEY_A + 1;
+ }
+ if (shift) {
+ // following graphics chars require shift key to input.
+ switch (windows_key_code) {
+ // ctrl-@ maps to \x00 (Null byte)
+ case ui::VKEY_2:
+ return 0;
+ // ctrl-^ maps to \x1E (Record separator, Information separator two)
+ case ui::VKEY_6:
+ return 0x1E;
+ // ctrl-_ maps to \x1F (Unit separator, Information separator one)
+ case ui::VKEY_OEM_MINUS:
+ return 0x1F;
+ // Returns 0 for all other keys to avoid inputting unexpected chars.
+ default:
+ return 0;
+ }
+ } else {
+ switch (windows_key_code) {
+ // ctrl-[ maps to \x1B (Escape)
+ case ui::VKEY_OEM_4:
+ return 0x1B;
+ // ctrl-\ maps to \x1C (File separator, Information separator four)
+ case ui::VKEY_OEM_5:
+ return 0x1C;
+ // ctrl-] maps to \x1D (Group separator, Information separator three)
+ case ui::VKEY_OEM_6:
+ return 0x1D;
+ // ctrl-Enter maps to \x0A (Line feed)
+ case ui::VKEY_RETURN:
+ return 0x0A;
+ // Returns 0 for all other keys to avoid inputting unexpected chars.
+ default:
+ return 0;
+ }
+ }
+}
+
+} // namespace
+
+namespace content {
+
+// WebKeyboardEvent -----------------------------------------------------------
+
+WebKeyboardEvent WebKeyboardEventBuilder::Build(const GdkEventKey* event) {
+ WebKeyboardEvent result;
+
+ result.timeStampSeconds = GdkEventTimeToWebEventTime(event->time);
+ result.modifiers = GdkStateToWebEventModifiers(NormalizeEventState(event));
+
+ switch (event->type) {
+ case GDK_KEY_RELEASE:
+ result.type = WebInputEvent::KeyUp;
+ break;
+ case GDK_KEY_PRESS:
+ result.type = WebInputEvent::RawKeyDown;
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ // According to MSDN:
+ // http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx
+ // Key events with Alt modifier and F10 are system key events.
+ // We just emulate this behavior. It's necessary to prevent webkit from
+ // processing keypress event generated by alt-d, etc.
+ // F10 is not special on Linux, so don't treat it as system key.
+ if (result.modifiers & WebInputEvent::AltKey)
+ result.isSystemKey = true;
+
+ // The key code tells us which physical key was pressed (for example, the
+ // A key went down or up). It does not determine whether A should be lower
+ // or upper case. This is what text does, which should be the keyval.
+ ui::KeyboardCode windows_key_code = GdkEventToWindowsKeyCode(event);
+ result.windowsKeyCode = GetWindowsKeyCodeWithoutLocation(windows_key_code);
+ result.modifiers |= GetLocationModifiersFromWindowsKeyCode(windows_key_code);
+ result.nativeKeyCode = event->hardware_keycode;
+
+ if (result.windowsKeyCode == ui::VKEY_RETURN) {
+ // We need to treat the enter key as a key press of character \r. This
+ // is apparently just how webkit handles it and what it expects.
+ result.unmodifiedText[0] = '\r';
+ } else {
+ // FIXME: fix for non BMP chars
+ result.unmodifiedText[0] =
+ static_cast<int>(gdk_keyval_to_unicode(event->keyval));
+ }
+
+ // If ctrl key is pressed down, then control character shall be input.
+ if (result.modifiers & WebInputEvent::ControlKey) {
+ result.text[0] =
+ GetControlCharacter(ui::KeyboardCode(result.windowsKeyCode),
+ result.modifiers & WebInputEvent::ShiftKey);
+ } else {
+ result.text[0] = result.unmodifiedText[0];
+ }
+
+ result.setKeyIdentifierFromWindowsKeyCode();
+
+ // FIXME: Do we need to set IsAutoRepeat?
+ if (IsKeyPadKeyval(event->keyval))
+ result.modifiers |= WebInputEvent::IsKeyPad;
+
+ return result;
+}
+
+WebKeyboardEvent WebKeyboardEventBuilder::Build(wchar_t character,
+ int state,
+ double timeStampSeconds) {
+ // keyboardEvent(const GdkEventKey*) depends on the GdkEventKey object and
+ // it is hard to use/ it from signal handlers which don't use GdkEventKey
+ // objects (e.g. GtkIMContext signal handlers.) For such handlers, this
+ // function creates a WebInputEvent::Char event without using a
+ // GdkEventKey object.
+ WebKeyboardEvent result;
+ result.type = WebKit::WebInputEvent::Char;
+ result.timeStampSeconds = timeStampSeconds;
+ result.modifiers = GdkStateToWebEventModifiers(state);
+ result.windowsKeyCode = character;
+ result.nativeKeyCode = character;
+ result.text[0] = character;
+ result.unmodifiedText[0] = character;
+
+ // According to MSDN:
+ // http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx
+ // Key events with Alt modifier and F10 are system key events.
+ // We just emulate this behavior. It's necessary to prevent webkit from
+ // processing keypress event generated by alt-d, etc.
+ // F10 is not special on Linux, so don't treat it as system key.
+ if (result.modifiers & WebInputEvent::AltKey)
+ result.isSystemKey = true;
+
+ return result;
+}
+
+// WebMouseEvent --------------------------------------------------------------
+
+WebMouseEvent WebMouseEventBuilder::Build(const GdkEventButton* event) {
+ WebMouseEvent result;
+
+ result.timeStampSeconds = GdkEventTimeToWebEventTime(event->time);
+
+ result.modifiers = GdkStateToWebEventModifiers(event->state);
+ result.x = static_cast<int>(event->x);
+ result.y = static_cast<int>(event->y);
+ result.windowX = result.x;
+ result.windowY = result.y;
+ result.globalX = static_cast<int>(event->x_root);
+ result.globalY = static_cast<int>(event->y_root);
+ result.clickCount = 0;
+
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ result.type = WebInputEvent::MouseDown;
+ break;
+ case GDK_BUTTON_RELEASE:
+ result.type = WebInputEvent::MouseUp;
+ break;
+ case GDK_3BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ default:
+ NOTREACHED();
+ }
+
+ result.button = WebMouseEvent::ButtonNone;
+ if (event->button == 1)
+ result.button = WebMouseEvent::ButtonLeft;
+ else if (event->button == 2)
+ result.button = WebMouseEvent::ButtonMiddle;
+ else if (event->button == 3)
+ result.button = WebMouseEvent::ButtonRight;
+
+ if (result.type == WebInputEvent::MouseDown) {
+ bool forgetPreviousClick = ShouldForgetPreviousClick(
+ event->window, event->time, event->x, event->y);
+
+ if (!forgetPreviousClick && result.button == last_click_button) {
+ ++num_clicks;
+ } else {
+ num_clicks = 1;
+
+ last_click_event_window = event->window;
+ last_click_x = event->x;
+ last_click_y = event->y;
+ last_click_button = result.button;
+ }
+ last_click_time = event->time;
+ }
+ result.clickCount = num_clicks;
+
+ return result;
+}
+
+WebMouseEvent WebMouseEventBuilder::Build(const GdkEventMotion* event) {
+ WebMouseEvent result;
+
+ result.timeStampSeconds = GdkEventTimeToWebEventTime(event->time);
+ result.modifiers = GdkStateToWebEventModifiers(event->state);
+ result.x = static_cast<int>(event->x);
+ result.y = static_cast<int>(event->y);
+ result.windowX = result.x;
+ result.windowY = result.y;
+ result.globalX = static_cast<int>(event->x_root);
+ result.globalY = static_cast<int>(event->y_root);
+
+ switch (event->type) {
+ case GDK_MOTION_NOTIFY:
+ result.type = WebInputEvent::MouseMove;
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ result.button = WebMouseEvent::ButtonNone;
+ if (event->state & GDK_BUTTON1_MASK)
+ result.button = WebMouseEvent::ButtonLeft;
+ else if (event->state & GDK_BUTTON2_MASK)
+ result.button = WebMouseEvent::ButtonMiddle;
+ else if (event->state & GDK_BUTTON3_MASK)
+ result.button = WebMouseEvent::ButtonRight;
+
+ if (ShouldForgetPreviousClick(event->window, event->time, event->x, event->y))
+ ResetClickCountState();
+
+ return result;
+}
+
+WebMouseEvent WebMouseEventBuilder::Build(const GdkEventCrossing* event) {
+ WebMouseEvent result;
+
+ result.timeStampSeconds = GdkEventTimeToWebEventTime(event->time);
+ result.modifiers = GdkStateToWebEventModifiers(event->state);
+ result.x = static_cast<int>(event->x);
+ result.y = static_cast<int>(event->y);
+ result.windowX = result.x;
+ result.windowY = result.y;
+ result.globalX = static_cast<int>(event->x_root);
+ result.globalY = static_cast<int>(event->y_root);
+
+ switch (event->type) {
+ case GDK_ENTER_NOTIFY:
+ case GDK_LEAVE_NOTIFY:
+ // Note that if we sent MouseEnter or MouseLeave to WebKit, it
+ // wouldn't work - they don't result in the proper JavaScript events.
+ // MouseMove does the right thing.
+ result.type = WebInputEvent::MouseMove;
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ result.button = WebMouseEvent::ButtonNone;
+ if (event->state & GDK_BUTTON1_MASK)
+ result.button = WebMouseEvent::ButtonLeft;
+ else if (event->state & GDK_BUTTON2_MASK)
+ result.button = WebMouseEvent::ButtonMiddle;
+ else if (event->state & GDK_BUTTON3_MASK)
+ result.button = WebMouseEvent::ButtonRight;
+
+ if (ShouldForgetPreviousClick(event->window, event->time, event->x, event->y))
+ ResetClickCountState();
+
+ return result;
+}
+
+// WebMouseWheelEvent ---------------------------------------------------------
+
+float WebMouseWheelEventBuilder::ScrollbarPixelsPerTick() {
+ // How much should we scroll per mouse wheel event?
+ // - Windows uses 3 lines by default and obeys a system setting.
+ // - Mozilla has a pref that lets you either use the "system" number of lines
+ // to scroll, or lets the user override it.
+ // For the "system" number of lines, it appears they've hardcoded 3.
+ // See case NS_MOUSE_SCROLL in content/events/src/nsEventStateManager.cpp
+ // and InitMouseScrollEvent in widget/src/gtk2/nsCommonWidget.cpp .
+ // - Gtk makes the scroll amount a function of the size of the scroll bar,
+ // which is not available to us here.
+ // Instead, we pick a number that empirically matches Firefox's behavior.
+ return 160.0f / 3.0f;
+}
+
+WebMouseWheelEvent WebMouseWheelEventBuilder::Build(
+ const GdkEventScroll* event) {
+ WebMouseWheelEvent result;
+
+ result.type = WebInputEvent::MouseWheel;
+ result.button = WebMouseEvent::ButtonNone;
+
+ result.timeStampSeconds = GdkEventTimeToWebEventTime(event->time);
+ result.modifiers = GdkStateToWebEventModifiers(event->state);
+ result.x = static_cast<int>(event->x);
+ result.y = static_cast<int>(event->y);
+ result.windowX = result.x;
+ result.windowY = result.y;
+ result.globalX = static_cast<int>(event->x_root);
+ result.globalY = static_cast<int>(event->y_root);
+
+ static const float scrollbarPixelsPerTick = ScrollbarPixelsPerTick();
+ switch (event->direction) {
+ case GDK_SCROLL_UP:
+ result.deltaY = scrollbarPixelsPerTick;
+ result.wheelTicksY = 1;
+ break;
+ case GDK_SCROLL_DOWN:
+ result.deltaY = -scrollbarPixelsPerTick;
+ result.wheelTicksY = -1;
+ break;
+ case GDK_SCROLL_LEFT:
+ result.deltaX = scrollbarPixelsPerTick;
+ result.wheelTicksX = 1;
+ break;
+ case GDK_SCROLL_RIGHT:
+ result.deltaX = -scrollbarPixelsPerTick;
+ result.wheelTicksX = -1;
+ break;
+ }
+
+ return result;
+}
+
+} // namespace content
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
new file mode 100644
index 00000000000..6fe16429b35
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_gtk.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_RENDERER_HOST_INPUT_WEB_INPUT_EVENT_BUILDERS_GTK_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_WEB_INPUT_EVENT_BUILDERS_GTK_H_
+
+#include "content/common/content_export.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "ui/events/keycodes/keyboard_codes.h"
+
+typedef struct _GdkEventButton GdkEventButton;
+typedef struct _GdkEventMotion GdkEventMotion;
+typedef struct _GdkEventCrossing GdkEventCrossing;
+typedef struct _GdkEventScroll GdkEventScroll;
+typedef struct _GdkEventKey GdkEventKey;
+
+namespace content {
+
+class CONTENT_EXPORT WebKeyboardEventBuilder {
+ public:
+ static WebKit::WebKeyboardEvent Build(const GdkEventKey* event);
+ static WebKit::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);
+};
+
+class CONTENT_EXPORT WebMouseWheelEventBuilder {
+ public:
+ static float ScrollbarPixelsPerTick();
+ static WebKit::WebMouseWheelEvent Build(
+ const GdkEventScroll* event);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_WEB_INPUT_EVENT_BUILDERS_GTK_H
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
new file mode 100644
index 00000000000..9498c9eb1be
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_gtk_unittest.cc
@@ -0,0 +1,171 @@
+// Copyright 2013 The Chromium Authors. All rights 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/web_input_event_builders_gtk.h"
+
+#include <gdk/gdk.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#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 content::WebMouseEventBuilder;
+using content::WebKeyboardEventBuilder;
+
+namespace {
+
+TEST(WebMouseEventBuilderTest, DoubleClick) {
+ GdkEventButton first_click;
+ first_click.type = GDK_BUTTON_PRESS;
+ first_click.window = static_cast<GdkWindow*>(GINT_TO_POINTER(1));
+ first_click.x = first_click.y = first_click.x_root = first_click.y_root = 100;
+ first_click.state = 0;
+ first_click.time = 0;
+ first_click.button = 1;
+
+ // Single click works.
+ WebMouseEvent first_click_events =
+ WebMouseEventBuilder::Build(&first_click);
+ EXPECT_EQ(1, first_click_events.clickCount);
+
+ // Make sure double click works.
+ GdkEventButton second_click = first_click;
+ second_click.time = first_click.time + 100;
+ WebMouseEvent second_click_events =
+ WebMouseEventBuilder::Build(&second_click);
+ EXPECT_EQ(2, second_click_events.clickCount);
+
+ // Reset the click count.
+ first_click.time += 10000;
+ first_click_events = WebMouseEventBuilder::Build(&first_click);
+ EXPECT_EQ(1, first_click_events.clickCount);
+
+ // Two clicks with a long gap in between aren't counted as a double click.
+ second_click = first_click;
+ second_click.time = first_click.time + 1000;
+ second_click_events = WebMouseEventBuilder::Build(&second_click);
+ EXPECT_EQ(1, second_click_events.clickCount);
+
+ // Reset the click count.
+ first_click.time += 10000;
+ first_click_events = WebMouseEventBuilder::Build(&first_click);
+ EXPECT_EQ(1, first_click_events.clickCount);
+
+ // Two clicks far apart (horizontally) aren't counted as a double click.
+ second_click = first_click;
+ second_click.time = first_click.time + 1;
+ second_click.x = first_click.x + 100;
+ second_click_events = WebMouseEventBuilder::Build(&second_click);
+ EXPECT_EQ(1, second_click_events.clickCount);
+
+ // Reset the click count.
+ first_click.time += 10000;
+ first_click_events = WebMouseEventBuilder::Build(&first_click);
+ EXPECT_EQ(1, first_click_events.clickCount);
+
+ // Two clicks far apart (vertically) aren't counted as a double click.
+ second_click = first_click;
+ second_click.time = first_click.time + 1;
+ second_click.x = first_click.y + 100;
+ second_click_events = WebMouseEventBuilder::Build(&second_click);
+ EXPECT_EQ(1, second_click_events.clickCount);
+
+ // Reset the click count.
+ first_click.time += 10000;
+ first_click_events = WebMouseEventBuilder::Build(&first_click);
+ EXPECT_EQ(1, first_click_events.clickCount);
+
+ // Two clicks on different windows aren't a double click.
+ second_click = first_click;
+ second_click.time = first_click.time + 1;
+ second_click.window = static_cast<GdkWindow*>(GINT_TO_POINTER(2));
+ second_click_events = WebMouseEventBuilder::Build(&second_click);
+ EXPECT_EQ(1, second_click_events.clickCount);
+}
+
+TEST(WebMouseEventBuilderTest, MouseUpClickCount) {
+ GdkEventButton mouse_down;
+ memset(&mouse_down, 0, sizeof(mouse_down));
+ mouse_down.type = GDK_BUTTON_PRESS;
+ mouse_down.window = static_cast<GdkWindow*>(GINT_TO_POINTER(1));
+ mouse_down.x = mouse_down.y = mouse_down.x_root = mouse_down.y_root = 100;
+ mouse_down.time = 0;
+ mouse_down.button = 1;
+
+ // Properly set the last click time, so that the internal state won't be
+ // affected by previous tests.
+ WebMouseEventBuilder::Build(&mouse_down);
+
+ mouse_down.time += 10000;
+ GdkEventButton mouse_up = mouse_down;
+ mouse_up.type = GDK_BUTTON_RELEASE;
+ WebMouseEvent mouse_down_event;
+ WebMouseEvent mouse_up_event;
+
+ // Click for three times.
+ for (int i = 1; i < 4; ++i) {
+ mouse_down.time += 100;
+ mouse_down_event = WebMouseEventBuilder::Build(&mouse_down);
+ EXPECT_EQ(i, mouse_down_event.clickCount);
+
+ mouse_up.time = mouse_down.time + 50;
+ mouse_up_event = WebMouseEventBuilder::Build(&mouse_up);
+ EXPECT_EQ(i, mouse_up_event.clickCount);
+ }
+
+ // Reset the click count.
+ mouse_down.time += 10000;
+ mouse_down_event = WebMouseEventBuilder::Build(&mouse_down);
+ EXPECT_EQ(1, mouse_down_event.clickCount);
+
+ // Moving the cursor for a significant distance will reset the click count to
+ // 0.
+ GdkEventMotion mouse_move;
+ memset(&mouse_move, 0, sizeof(mouse_move));
+ mouse_move.type = GDK_MOTION_NOTIFY;
+ mouse_move.window = mouse_down.window;
+ mouse_move.time = mouse_down.time;
+ mouse_move.x = mouse_move.y = mouse_move.x_root = mouse_move.y_root =
+ mouse_down.x + 100;
+ WebMouseEventBuilder::Build(&mouse_move);
+
+ mouse_up.time = mouse_down.time + 50;
+ mouse_up_event = WebMouseEventBuilder::Build(&mouse_up);
+ EXPECT_EQ(0, mouse_up_event.clickCount);
+
+ // Reset the click count.
+ mouse_down.time += 10000;
+ mouse_down_event = WebMouseEventBuilder::Build(&mouse_down);
+ EXPECT_EQ(1, mouse_down_event.clickCount);
+
+ // Moving the cursor with a significant delay will reset the click count to 0.
+ mouse_move.time = mouse_down.time + 1000;
+ mouse_move.x = mouse_move.y = mouse_move.x_root = mouse_move.y_root =
+ mouse_down.x;
+ WebMouseEventBuilder::Build(&mouse_move);
+
+ mouse_up.time = mouse_move.time + 50;
+ mouse_up_event = WebMouseEventBuilder::Build(&mouse_up);
+ EXPECT_EQ(0, mouse_up_event.clickCount);
+}
+
+TEST(WebKeyboardEventBuilderTest, NumPadConversion) {
+ // Construct a GDK input event for the numpad "5" key.
+ char five[] = "5";
+ GdkEventKey gdk_event;
+ memset(&gdk_event, 0, sizeof(GdkEventKey));
+ gdk_event.type = GDK_KEY_PRESS;
+ gdk_event.keyval = GDK_KP_5;
+ gdk_event.string = five;
+
+ // Numpad flag should be set on the WebKeyboardEvent.
+ WebKeyboardEvent web_event = WebKeyboardEventBuilder::Build(&gdk_event);
+ EXPECT_TRUE(web_event.modifiers & WebInputEvent::IsKeyPad);
+}
+
+} // anonymous namespace
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 75870ebc7cc..1abaf8cf34e 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
@@ -6,7 +6,7 @@
#define CONTENT_BROWSER_RENDERER_HOST_INPUT_WEB_INPUT_EVENT_UTIL_H_
#include "content/common/content_export.h"
-#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/events/keycodes/keyboard_codes.h"
namespace WebKit {
class WebKeyboardEvent;
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 34e4ee96165..e7dc1549cb9 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
@@ -6,7 +6,7 @@
#define CONTENT_BROWSER_RENDERER_HOST_INPUT_WEB_INPUT_EVENT_UTIL_POSIX_H_
#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/events/keycodes/keyboard_codes.h"
namespace content {
diff --git a/chromium/content/browser/renderer_host/media/audio_input_device_manager.cc b/chromium/content/browser/renderer_host/media/audio_input_device_manager.cc
index b4959567a31..50bb3ec8310 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
@@ -34,7 +34,8 @@ AudioInputDeviceManager::AudioInputDeviceManager(
StreamDeviceInfo fake_device(MEDIA_DEVICE_AUDIO_CAPTURE,
media::AudioManagerBase::kDefaultDeviceName,
media::AudioManagerBase::kDefaultDeviceId,
- 44100, media::CHANNEL_LAYOUT_STEREO, false);
+ 44100, media::CHANNEL_LAYOUT_STEREO,
+ 0, false);
fake_device.session_id = kFakeOpenSessionId;
devices_.push_back(fake_device);
}
@@ -169,19 +170,37 @@ void AudioInputDeviceManager::OpenOnDeviceThread(
DCHECK(IsOnDeviceThread());
StreamDeviceInfo out(info.device.type, info.device.name, info.device.id,
- 0, 0, false);
+ 0, 0, 0, false);
out.session_id = session_id;
+
+ MediaStreamDevice::AudioDeviceParameters& input_params = out.device.input;
+
if (use_fake_device_) {
// Don't need to query the hardware information if using fake device.
- out.device.sample_rate = 44100;
- out.device.channel_layout = media::CHANNEL_LAYOUT_STEREO;
+ input_params.sample_rate = 44100;
+ input_params.channel_layout = media::CHANNEL_LAYOUT_STEREO;
} else {
// Get the preferred sample rate and channel configuration for the
// audio device.
media::AudioParameters params =
audio_manager_->GetInputStreamParameters(info.device.id);
- out.device.sample_rate = params.sample_rate();
- out.device.channel_layout = params.channel_layout();
+ input_params.sample_rate = params.sample_rate();
+ input_params.channel_layout = params.channel_layout();
+ input_params.frames_per_buffer = params.frames_per_buffer();
+
+ // Add preferred output device information if a matching output device
+ // exists.
+ out.device.matched_output_device_id =
+ audio_manager_->GetAssociatedOutputDeviceID(info.device.id);
+ if (!out.device.matched_output_device_id.empty()) {
+ params = audio_manager_->GetOutputStreamParameters(
+ out.device.matched_output_device_id);
+ MediaStreamDevice::AudioDeviceParameters& matched_output_params =
+ out.device.matched_output;
+ matched_output_params.sample_rate = params.sample_rate();
+ matched_output_params.channel_layout = params.channel_layout();
+ matched_output_params.frames_per_buffer = params.frames_per_buffer();
+ }
}
// Return the |session_id| through the listener by posting a task on
@@ -206,6 +225,7 @@ void AudioInputDeviceManager::OpenedOnIOThread(int session_id,
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK_EQ(session_id, info.session_id);
DCHECK(GetDevice(session_id) == devices_.end());
+
devices_.push_back(info);
if (listener_)
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 03b31d2845e..25d8a1722e9 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
@@ -177,7 +177,8 @@ 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, false);
+ stream_type, device_name, device_id, sample_rate, channel_config, 2048,
+ false);
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 4a2f731a81c..1c021095676 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc
@@ -51,11 +51,12 @@ AudioInputRendererHost::AudioEntry::~AudioEntry() {}
AudioInputRendererHost::AudioInputRendererHost(
media::AudioManager* audio_manager,
MediaStreamManager* media_stream_manager,
- AudioMirroringManager* audio_mirroring_manager)
+ AudioMirroringManager* audio_mirroring_manager,
+ media::UserInputMonitor* user_input_monitor)
: audio_manager_(audio_manager),
media_stream_manager_(media_stream_manager),
- audio_mirroring_manager_(audio_mirroring_manager) {
-}
+ audio_mirroring_manager_(audio_mirroring_manager),
+ user_input_monitor_(user_input_monitor) {}
AudioInputRendererHost::~AudioInputRendererHost() {
DCHECK(audio_entries_.empty());
@@ -272,20 +273,23 @@ void AudioInputRendererHost::OnCreateStream(
entry->controller = media::AudioInputController::CreateForStream(
audio_manager_->GetMessageLoop(),
this,
- WebContentsAudioInputStream::Create(
- device_id, audio_params, audio_manager_->GetWorkerLoop(),
- audio_mirroring_manager_),
- entry->writer.get());
+ WebContentsAudioInputStream::Create(device_id,
+ audio_params,
+ audio_manager_->GetWorkerLoop(),
+ audio_mirroring_manager_),
+ entry->writer.get(),
+ user_input_monitor_);
} else {
// TODO(henrika): replace CreateLowLatency() with Create() as soon
// as satish has ensured that Speech Input also uses the default low-
// latency path. See crbug.com/112472 for details.
- entry->controller = media::AudioInputController::CreateLowLatency(
- audio_manager_,
- this,
- audio_params,
- device_id,
- entry->writer.get());
+ entry->controller =
+ media::AudioInputController::CreateLowLatency(audio_manager_,
+ this,
+ audio_params,
+ device_id,
+ entry->writer.get(),
+ user_input_monitor_);
}
if (!entry->controller.get()) {
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 d16ebfad86a..5df1fc6f2f0 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
@@ -44,6 +44,7 @@
namespace media {
class AudioManager;
class AudioParameters;
+class UserInputMonitor;
}
namespace content {
@@ -55,10 +56,11 @@ class CONTENT_EXPORT AudioInputRendererHost
public media::AudioInputController::EventHandler {
public:
// Called from UI thread from the owner of this object.
- AudioInputRendererHost(
- media::AudioManager* audio_manager,
- MediaStreamManager* media_stream_manager,
- AudioMirroringManager* audio_mirroring_manager);
+ // |user_input_monitor| is used for typing detection and can be NULL.
+ AudioInputRendererHost(media::AudioManager* audio_manager,
+ MediaStreamManager* media_stream_manager,
+ AudioMirroringManager* audio_mirroring_manager,
+ media::UserInputMonitor* user_input_monitor);
// BrowserMessageFilter implementation.
virtual void OnChannelClosing() OVERRIDE;
@@ -154,6 +156,9 @@ class CONTENT_EXPORT AudioInputRendererHost
// A map of stream IDs to audio sources.
AudioEntryMap audio_entries_;
+ // Raw pointer of the UserInputMonitor.
+ media::UserInputMonitor* user_input_monitor_;
+
DISALLOW_COPY_AND_ASSIGN(AudioInputRendererHost);
};
diff --git a/chromium/content/browser/renderer_host/media/audio_input_sync_writer.cc b/chromium/content/browser/renderer_host/media/audio_input_sync_writer.cc
index 572abf3e1c6..369e0a87f20 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_sync_writer.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_sync_writer.cc
@@ -29,14 +29,17 @@ void AudioInputSyncWriter::UpdateRecordedBytes(uint32 bytes) {
socket_->Send(&bytes, sizeof(bytes));
}
-uint32 AudioInputSyncWriter::Write(
- const void* data, uint32 size, double volume) {
+uint32 AudioInputSyncWriter::Write(const void* data,
+ uint32 size,
+ double volume,
+ bool key_pressed) {
uint8* ptr = static_cast<uint8*>(shared_memory_->memory());
ptr += current_segment_id_ * shared_memory_segment_size_;
media::AudioInputBuffer* buffer =
reinterpret_cast<media::AudioInputBuffer*>(ptr);
buffer->params.volume = volume;
buffer->params.size = size;
+ buffer->params.key_pressed = key_pressed;
memcpy(buffer->audio, data, size);
if (++current_segment_id_ >= shared_memory_segment_count_)
diff --git a/chromium/content/browser/renderer_host/media/audio_input_sync_writer.h b/chromium/content/browser/renderer_host/media/audio_input_sync_writer.h
index 4cfe9e3f396..d16911f20c3 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_sync_writer.h
+++ b/chromium/content/browser/renderer_host/media/audio_input_sync_writer.h
@@ -28,7 +28,10 @@ class AudioInputSyncWriter : public media::AudioInputController::SyncWriter {
// media::AudioOutputController::SyncWriter implementation.
virtual void UpdateRecordedBytes(uint32 bytes) OVERRIDE;
- virtual uint32 Write(const void* data, uint32 size, double volume) OVERRIDE;
+ virtual uint32 Write(const void* data,
+ uint32 size,
+ double volume,
+ bool key_pressed) OVERRIDE;
virtual void Close() OVERRIDE;
bool Init();
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 53f2eb2ae90..c09dc6ce08b 100644
--- a/chromium/content/browser/renderer_host/media/audio_renderer_host.cc
+++ b/chromium/content/browser/renderer_host/media/audio_renderer_host.cc
@@ -36,6 +36,7 @@ class AudioRendererHost::AudioEntry
int stream_id,
int render_view_id,
const media::AudioParameters& params,
+ const std::string& output_device_id,
const std::string& input_device_id,
scoped_ptr<base::SharedMemory> shared_memory,
scoped_ptr<media::AudioOutputController::SyncReader> reader);
@@ -88,6 +89,7 @@ class AudioRendererHost::AudioEntry
AudioRendererHost::AudioEntry::AudioEntry(
AudioRendererHost* host, int stream_id, int render_view_id,
const media::AudioParameters& params,
+ const std::string& output_device_id,
const std::string& input_device_id,
scoped_ptr<base::SharedMemory> shared_memory,
scoped_ptr<media::AudioOutputController::SyncReader> reader)
@@ -95,7 +97,8 @@ AudioRendererHost::AudioEntry::AudioEntry(
stream_id_(stream_id),
render_view_id_(render_view_id),
controller_(media::AudioOutputController::Create(
- host->audio_manager_, this, params, input_device_id, reader.get())),
+ host->audio_manager_, this, params, output_device_id,
+ input_device_id, reader.get())),
shared_memory_(shared_memory.Pass()),
reader_(reader.Pass()) {
DCHECK(controller_.get());
@@ -301,10 +304,16 @@ void AudioRendererHost::OnCreateStream(
// When the |input_channels| is valid, clients are trying to create a unified
// IO stream which opens an input device mapping to the |session_id|.
- std::string input_device_id;
+ // Initialize the |output_device_id| to an empty string which indicates that
+ // the default device should be used. If a StreamDeviceInfo instance was found
+ // though, then we use the matched output device.
+ std::string input_device_id, output_device_id;
+ const StreamDeviceInfo* info = media_stream_manager_->
+ audio_input_device_manager()->GetOpenedDeviceInfoById(session_id);
+ if (info)
+ output_device_id = info->device.matched_output_device_id;
+
if (input_channels > 0) {
- const StreamDeviceInfo* info = media_stream_manager_->
- audio_input_device_manager()->GetOpenedDeviceInfoById(session_id);
if (!info) {
SendErrorMessage(stream_id);
DLOG(WARNING) << "No permission has been granted to input stream with "
@@ -346,16 +355,18 @@ void AudioRendererHost::OnCreateStream(
media_observer->OnCreatingAudioStream(render_process_id_, render_view_id);
scoped_ptr<AudioEntry> entry(new AudioEntry(
- this, stream_id, render_view_id, params, input_device_id,
- shared_memory.Pass(),
+ this, stream_id, render_view_id, params, output_device_id,
+ input_device_id, shared_memory.Pass(),
reader.PassAs<media::AudioOutputController::SyncReader>()));
if (mirroring_manager_) {
mirroring_manager_->AddDiverter(
render_process_id_, entry->render_view_id(), entry->controller());
}
audio_entries_.insert(std::make_pair(stream_id, entry.release()));
- if (media_internals_)
- media_internals_->OnSetAudioStreamStatus(this, stream_id, "created");
+ if (media_internals_) {
+ media_internals_->OnAudioStreamCreated(
+ this, stream_id, params, input_device_id);
+ }
}
void AudioRendererHost::OnPlayStream(int stream_id) {
diff --git a/chromium/content/browser/renderer_host/media/audio_renderer_host_unittest.cc b/chromium/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
index 42fecc07a96..26c0963e5e8 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
@@ -207,8 +207,6 @@ class AudioRendererHostTest : public testing::Test {
}
void Create(bool unified_stream) {
- EXPECT_CALL(*observer_,
- OnSetAudioStreamStatus(_, kStreamId, "created"));
EXPECT_CALL(*host_.get(), OnStreamCreated(kStreamId, _))
.WillOnce(DoAll(Assign(&is_stream_active_, true),
QuitMessageLoop(message_loop_.get())));
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 5a03e465533..16e69bf8ad0 100644
--- a/chromium/content/browser/renderer_host/media/desktop_capture_device.cc
+++ b/chromium/content/browser/renderer_host/media/desktop_capture_device.cc
@@ -23,7 +23,19 @@
namespace content {
namespace {
+
const int kBytesPerPixel = 4;
+
+webrtc::DesktopRect ComputeLetterboxRect(
+ const webrtc::DesktopSize& max_size,
+ const webrtc::DesktopSize& source_size) {
+ gfx::Rect result = media::ComputeLetterboxRegion(
+ gfx::Rect(0, 0, max_size.width(), max_size.height()),
+ gfx::Size(source_size.width(), source_size.height()));
+ return webrtc::DesktopRect::MakeLTRB(
+ result.x(), result.y(), result.right(), result.bottom());
+}
+
} // namespace
class DesktopCaptureDevice::Core
@@ -34,8 +46,7 @@ class DesktopCaptureDevice::Core
scoped_ptr<webrtc::DesktopCapturer> capturer);
// Implementation of VideoCaptureDevice methods.
- void Allocate(int width, int height,
- int frame_rate,
+ void Allocate(const media::VideoCaptureCapability& capture_format,
EventHandler* event_handler);
void Start();
void Stop();
@@ -51,11 +62,16 @@ class DesktopCaptureDevice::Core
// Helper methods that run on the |task_runner_|. Posted from the
// corresponding public methods.
- void DoAllocate(int width, int height, int frame_rate);
+ void DoAllocate(const media::VideoCaptureCapability& capture_format);
void DoStart();
void DoStop();
void DoDeAllocate();
+ // 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();
@@ -78,24 +94,23 @@ class DesktopCaptureDevice::Core
base::Lock event_handler_lock_;
EventHandler* event_handler_;
- // Requested size specified to Allocate().
- webrtc::DesktopSize requested_size_;
-
- // Frame rate specified to Allocate().
- int frame_rate_;
+ // Requested video capture format (width, height, frame rate, etc).
+ media::VideoCaptureCapability requested_format_;
- // Empty until the first frame has been captured, and the output dimensions
- // chosen based on the capture frame's size, and any caller-supplied
- // size constraints.
- webrtc::DesktopSize output_size_;
+ // Actual video capture format being generated.
+ media::VideoCaptureCapability capture_format_;
- // Size of the most recently received frame.
+ // Size of frame most recently captured from the source.
webrtc::DesktopSize previous_frame_size_;
- // DesktopFrame into which captured frames are scaled, if the source size does
- // not match |output_size_|. If the source and output have the same dimensions
- // then this is NULL.
- scoped_ptr<webrtc::DesktopFrame> scaled_frame_;
+ // DesktopFrame into which captured frames are down-scaled and/or letterboxed,
+ // depending upon the caller's requested capture capabilities. If frames can
+ // be returned to the caller directly then this is NULL.
+ scoped_ptr<webrtc::DesktopFrame> output_frame_;
+
+ // Sub-rectangle of |output_frame_| into which the source will be scaled
+ // 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.
@@ -125,12 +140,12 @@ DesktopCaptureDevice::Core::Core(
DesktopCaptureDevice::Core::~Core() {
}
-void DesktopCaptureDevice::Core::Allocate(int width, int height,
- int frame_rate,
- EventHandler* event_handler) {
- DCHECK_GT(width, 0);
- DCHECK_GT(height, 0);
- DCHECK_GT(frame_rate, 0);
+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_);
@@ -139,7 +154,7 @@ void DesktopCaptureDevice::Core::Allocate(int width, int height,
task_runner_->PostTask(
FROM_HERE,
- base::Bind(&Core::DoAllocate, this, width, height, frame_rate));
+ base::Bind(&Core::DoAllocate, this, capture_format));
}
void DesktopCaptureDevice::Core::Start() {
@@ -180,95 +195,76 @@ void DesktopCaptureDevice::Core::OnCaptureCompleted(
scoped_ptr<webrtc::DesktopFrame> owned_frame(frame);
- // If an |output_size_| hasn't yet been chosen then choose one, based upon
- // the source frame size and the requested size supplied to Allocate().
- if (output_size_.is_empty()) {
- // Treat the requested size as upper bounds on width & height.
- // TODO(wez): Constraints should be passed from getUserMedia to Allocate.
- output_size_.set(
- std::min(frame->size().width(), requested_size_.width()),
- std::min(frame->size().height(), requested_size_.height()));
-
- // Inform the EventHandler of the output dimensions, format and frame rate.
- media::VideoCaptureCapability caps;
- caps.width = output_size_.width();
- caps.height = output_size_.height();
- caps.frame_rate = frame_rate_;
- caps.color = media::VideoCaptureCapability::kARGB;
- caps.expected_capture_delay =
- base::Time::kMillisecondsPerSecond / frame_rate_;
- caps.interlaced = false;
-
- base::AutoLock auto_lock(event_handler_lock_);
- if (event_handler_)
- event_handler_->OnFrameInfo(caps);
- }
+ // Handle initial frame size and size changes.
+ RefreshCaptureFormat(frame->size());
if (!started_)
return;
- size_t output_bytes = output_size_.width() * output_size_.height() *
+ webrtc::DesktopSize output_size(capture_format_.width,
+ capture_format_.height);
+ size_t output_bytes = output_size.width() * output_size.height() *
webrtc::DesktopFrame::kBytesPerPixel;
+ const uint8_t* output_data = NULL;
- if (frame->size().equals(output_size_)) {
+ if (frame->size().equals(output_size)) {
// If the captured frame matches the output size, we can return the pixel
// data directly, without scaling.
- scaled_frame_.reset();
-
- base::AutoLock auto_lock(event_handler_lock_);
- if (event_handler_) {
- event_handler_->OnIncomingCapturedFrame(
- frame->data(), output_bytes, base::Time::Now(), 0, false, false);
+ output_data = frame->data();
+ } else {
+ // Otherwise we need to down-scale and/or letterbox to the target format.
+
+ // Allocate a buffer of the correct size to scale the frame into.
+ // |output_frame_| is cleared whenever |output_rect_| changes, so we don't
+ // need to worry about clearing out stale pixel data in letterboxed areas.
+ if (!output_frame_) {
+ output_frame_.reset(new webrtc::BasicDesktopFrame(output_size));
+ memset(output_frame_->data(), 0, output_bytes);
}
- return;
- }
-
- // If the output size differs from the frame size (e.g. the source has changed
- // from its original dimensions, or the caller specified size constraints)
- // then we need to scale the image.
- if (!scaled_frame_)
- scaled_frame_.reset(new webrtc::BasicDesktopFrame(output_size_));
- DCHECK(scaled_frame_->size().equals(output_size_));
-
- // If the source frame size changed then clear |scaled_frame_|'s pixels.
- if (!previous_frame_size_.equals(frame->size())) {
- previous_frame_size_ = frame->size();
- memset(scaled_frame_->data(), 0, output_bytes);
+ DCHECK(output_frame_->size().equals(output_size));
+
+ // TODO(wez): Optimize this to scale only changed portions of the output,
+ // using ARGBScaleClip().
+ uint8_t* output_rect_data = output_frame_->data() +
+ output_frame_->stride() * output_rect_.top() +
+ webrtc::DesktopFrame::kBytesPerPixel * output_rect_.left();
+ libyuv::ARGBScale(frame->data(), frame->stride(),
+ frame->size().width(), frame->size().height(),
+ output_rect_data, output_frame_->stride(),
+ output_rect_.width(), output_rect_.height(),
+ libyuv::kFilterBilinear);
+ output_data = output_frame_->data();
}
- // Determine the output size preserving aspect, and center in output buffer.
- gfx::Rect scaled_rect = media::ComputeLetterboxRegion(
- gfx::Rect(0, 0, output_size_.width(), output_size_.height()),
- gfx::Size(frame->size().width(), frame->size().height()));
- uint8* scaled_data = scaled_frame_->data() +
- scaled_frame_->stride() * scaled_rect.y() +
- webrtc::DesktopFrame::kBytesPerPixel * scaled_rect.x();
-
- // TODO(wez): Optimize this to scale only changed portions of the output,
- // using ARGBScaleClip().
- libyuv::ARGBScale(frame->data(), frame->stride(),
- frame->size().width(), frame->size().height(),
- scaled_data, scaled_frame_->stride(),
- scaled_rect.width(), scaled_rect.height(),
- libyuv::kFilterBilinear);
-
base::AutoLock auto_lock(event_handler_lock_);
if (event_handler_) {
- event_handler_->OnIncomingCapturedFrame(
- scaled_frame_->data(), output_bytes,
- base::Time::Now(), 0, false, false);
+ event_handler_->OnIncomingCapturedFrame(output_data, output_bytes,
+ base::Time::Now(), 0, false, false);
}
}
-void DesktopCaptureDevice::Core::DoAllocate(int width,
- int height,
- int frame_rate) {
+void DesktopCaptureDevice::Core::DoAllocate(
+ const media::VideoCaptureCapability& capture_format) {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
DCHECK(desktop_capturer_);
- requested_size_.set(width, height);
- output_size_.set(0, 0);
- frame_rate_ = frame_rate;
+ requested_format_ = capture_format;
+
+ // 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;
+ }
+
+ // This capturer always outputs ARGB, non-interlaced.
+ capture_format_.color = media::PIXEL_FORMAT_ARGB;
+ capture_format_.interlaced = false;
desktop_capturer_->Start(this);
@@ -288,14 +284,63 @@ void DesktopCaptureDevice::Core::DoStart() {
void DesktopCaptureDevice::Core::DoStop() {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
started_ = false;
- scaled_frame_.reset();
+ output_frame_.reset();
+ previous_frame_size_.set(0, 0);
}
void DesktopCaptureDevice::Core::DoDeAllocate() {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
DoStop();
desktop_capturer_.reset();
- output_size_.set(0, 0);
+}
+
+void DesktopCaptureDevice::Core::RefreshCaptureFormat(
+ const webrtc::DesktopSize& frame_size) {
+ if (previous_frame_size_.equals(frame_size))
+ return;
+
+ // Clear the output frame, if any, since it will either need resizing, or
+ // clearing of stale data in letterbox areas, anyway.
+ output_frame_.reset();
+
+ if (previous_frame_size_.is_empty() ||
+ requested_format_.frame_size_type ==
+ media::VariableResolutionVideoCaptureDevice) {
+ // 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) {
+ output_rect_ = ComputeLetterboxRect(
+ webrtc::DesktopSize(requested_format_.width,
+ requested_format_.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_);
+ }
+ }
+ }
+ } else {
+ // Otherwise the output frame size cannot change, so just scale and
+ // letterbox.
+ output_rect_ = ComputeLetterboxRect(
+ webrtc::DesktopSize(capture_format_.width, capture_format_.height),
+ frame_size);
+ }
+
+ previous_frame_size_ = frame_size;
}
void DesktopCaptureDevice::Core::ScheduleCaptureTimer() {
@@ -303,7 +348,7 @@ void DesktopCaptureDevice::Core::ScheduleCaptureTimer() {
capture_task_posted_ = true;
task_runner_->PostDelayedTask(
FROM_HERE, base::Bind(&Core::OnCaptureTimer, this),
- base::TimeDelta::FromSeconds(1) / frame_rate_);
+ base::TimeDelta::FromSeconds(1) / capture_format_.frame_rate);
}
void DesktopCaptureDevice::Core::OnCaptureTimer() {
@@ -343,11 +388,10 @@ scoped_ptr<media::VideoCaptureDevice> DesktopCaptureDevice::Create(
case DesktopMediaID::TYPE_SCREEN: {
scoped_ptr<webrtc::DesktopCapturer> capturer;
-#if defined(OS_CHROMEOS) && !defined(ARCH_CPU_ARMEL) && defined(USE_X11)
+#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. However ARM driver seems to not support this properly, so
- // disable it for ARM. See http://crbug.com/230105 .
+ // so use it.
capturer.reset(webrtc::ScreenCapturer::CreateWithXDamage(true));
#elif defined(OS_WIN)
// ScreenCapturerWin disables Aero by default. We don't want it disabled
@@ -394,11 +438,8 @@ DesktopCaptureDevice::~DesktopCaptureDevice() {
void DesktopCaptureDevice::Allocate(
const media::VideoCaptureCapability& capture_format,
- EventHandler* observer) {
- core_->Allocate(capture_format.width,
- capture_format.height,
- capture_format.frame_rate,
- observer);
+ EventHandler* event_handler) {
+ core_->Allocate(capture_format, event_handler);
}
void DesktopCaptureDevice::Start() {
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 84422d3c5c9..8f60c7de1b8 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::VideoCaptureDevice {
+class CONTENT_EXPORT DesktopCaptureDevice : public media::VideoCaptureDevice1 {
public:
// Creates capturer for the specified |source| and then creates
// DesktopCaptureDevice for it. May return NULL in case of a failure (e.g. if
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 0f14585ea90..2b6479e3cb2 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
@@ -17,7 +17,9 @@
#include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"
using ::testing::_;
+using ::testing::AnyNumber;
using ::testing::DoAll;
+using ::testing::Expectation;
using ::testing::InvokeWithoutArgs;
using ::testing::SaveArg;
@@ -25,6 +27,10 @@ namespace content {
namespace {
+MATCHER_P2(EqualsCaptureCapability, width, height, "") {
+ return arg.width == width && arg.height == height;
+}
+
const int kTestFrameWidth1 = 100;
const int kTestFrameHeight1 = 100;
const int kTestFrameWidth2 = 200;
@@ -38,6 +44,8 @@ class MockFrameObserver : public media::VideoCaptureDevice::EventHandler {
MOCK_METHOD0(ReserveOutputBuffer, scoped_refptr<media::VideoFrame>());
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,
@@ -124,7 +132,7 @@ TEST_F(DesktopCaptureDeviceTest, MAYBE_Capture) {
InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));
media::VideoCaptureCapability capture_format(
- 640, 480, kFrameRate, media::VideoCaptureCapability::kI420, 0, false,
+ 640, 480, kFrameRate, media::PIXEL_FORMAT_I420, 0, false,
media::ConstantResolutionVideoCaptureDevice);
capture_device.Allocate(capture_format, &frame_observer);
capture_device.Start();
@@ -135,14 +143,15 @@ TEST_F(DesktopCaptureDeviceTest, MAYBE_Capture) {
EXPECT_GT(caps.width, 0);
EXPECT_GT(caps.height, 0);
EXPECT_EQ(kFrameRate, caps.frame_rate);
- EXPECT_EQ(media::VideoCaptureCapability::kARGB, caps.color);
+ EXPECT_EQ(media::PIXEL_FORMAT_ARGB, caps.color);
EXPECT_FALSE(caps.interlaced);
EXPECT_EQ(caps.width * caps.height * 4, frame_size);
}
-// Test that screen capturer can handle resolution change without crashing.
-TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChange) {
+// Test that screen capturer behaves correctly if the source frame size changes
+// but the caller cannot cope with variable resolution output.
+TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeConstantResolution) {
FakeScreenCapturer* mock_capturer = new FakeScreenCapturer();
DesktopCaptureDevice capture_device(
@@ -154,11 +163,14 @@ TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChange) {
int frame_size;
MockFrameObserver frame_observer;
- EXPECT_CALL(frame_observer, OnFrameInfo(_))
+ 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)));
@@ -167,27 +179,93 @@ TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChange) {
kTestFrameWidth1,
kTestFrameHeight1,
kFrameRate,
- media::VideoCaptureCapability::kI420,
+ media::PIXEL_FORMAT_I420,
0,
false,
media::ConstantResolutionVideoCaptureDevice);
+
capture_device.Allocate(capture_format, &frame_observer);
capture_device.Start();
- // Capture first frame.
+
+ // Capture at least two frames, to ensure that the source frame size has
+ // changed while capturing.
EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
done_event.Reset();
- // Capture second frame.
EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
+
capture_device.Stop();
capture_device.DeAllocate();
EXPECT_EQ(kTestFrameWidth1, caps.width);
EXPECT_EQ(kTestFrameHeight1, caps.height);
EXPECT_EQ(kFrameRate, caps.frame_rate);
- EXPECT_EQ(media::VideoCaptureCapability::kARGB, caps.color);
+ EXPECT_EQ(media::PIXEL_FORMAT_ARGB, caps.color);
EXPECT_FALSE(caps.interlaced);
EXPECT_EQ(caps.width * caps.height * 4, frame_size);
}
+// Test that screen capturer behaves correctly if the source frame size changes
+// and the caller can cope with variable resolution output.
+TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeVariableResolution) {
+ FakeScreenCapturer* mock_capturer = new FakeScreenCapturer();
+
+ DesktopCaptureDevice capture_device(
+ worker_pool_->GetSequencedTaskRunner(worker_pool_->GetSequenceToken()),
+ scoped_ptr<webrtc::DesktopCapturer>(mock_capturer));
+
+ media::VideoCaptureCapability caps;
+ 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)
+ .WillRepeatedly(
+ InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal));
+
+ media::VideoCaptureCapability capture_format(
+ kTestFrameWidth2,
+ kTestFrameHeight2,
+ kFrameRate,
+ media::PIXEL_FORMAT_I420,
+ 0,
+ false,
+ media::VariableResolutionVideoCaptureDevice);
+
+ capture_device.Allocate(capture_format, &frame_observer);
+ capture_device.Start();
+
+ // Capture at least three frames, to ensure that the source frame size has
+ // changed at least twice while capturing.
+ EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
+ done_event.Reset();
+ EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
+ done_event.Reset();
+ EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
+
+ capture_device.Stop();
+ capture_device.DeAllocate();
+
+ 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);
+}
+
} // 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 770e800d402..96a5de2e194 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
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-
#include "content/browser/renderer_host/media/device_request_message_filter.h"
#include "base/strings/string_number_conversions.h"
@@ -193,7 +192,13 @@ bool DeviceRequestMessageFilter::DoesRawIdMatchGuid(
bool result = hmac.Init(security_origin.spec());
DCHECK(result);
std::vector<uint8> converted_guid;
- base::HexStringToBytes(device_guid, &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]),
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 048e2157871..b684954384c 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
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_CENTER_HOST_H_
-#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_CENTER_HOST_H_
+#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_DEVICE_REQUEST_MESSAGE_FILTER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_DEVICE_REQUEST_MESSAGE_FILTER_H_
#include <map>
#include <string>
@@ -75,4 +75,4 @@ class CONTENT_EXPORT DeviceRequestMessageFilter : public BrowserMessageFilter,
} // namespace content
-#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_CENTER_HOST_H_
+#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_DEVICE_REQUEST_MESSAGE_FILTER_H_
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 04a7bb69eea..0daad820084 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
@@ -301,4 +301,20 @@ 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_unittest.cc b/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
index 05804266035..2b7d6836326 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
@@ -274,16 +274,6 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateThreeStreams) {
EXPECT_EQ(host_->NumberOfStreams(), 0u);
}
-TEST_F(MediaStreamDispatcherHostTest, FailOpenVideoDevice) {
- StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
-
- media::FakeVideoCaptureDevice::SetFailNextCreate();
- SetupFakeUI(false);
- EXPECT_CALL(*host_.get(),
- OnStreamGenerationFailed(kRenderId, kPageRequestId));
- GenerateStreamAndWaitForResult(kPageRequestId, options);
-}
-
TEST_F(MediaStreamDispatcherHostTest, CancelPendingStreamsOnChannelClosing) {
StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
diff --git a/chromium/content/browser/renderer_host/media/media_stream_manager.cc b/chromium/content/browser/renderer_host/media/media_stream_manager.cc
index 449331198bd..4c234b66ab1 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_manager.cc
@@ -740,8 +740,8 @@ void MediaStreamManager::Opened(MediaStreamType stream_type,
audio_input_device_manager_->GetOpenedDeviceInfoById(
device_it->session_id);
DCHECK_EQ(info->device.id, device_it->device.id);
- device_it->device.sample_rate = info->device.sample_rate;
- device_it->device.channel_layout = info->device.channel_layout;
+ 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)) {
@@ -949,8 +949,8 @@ void MediaStreamManager::HandleAccessRequestResponse(
if (sample_rate <= 0 || sample_rate > 96000)
sample_rate = 44100;
- device_info.device.sample_rate = sample_rate;
- device_info.device.channel_layout = media::CHANNEL_LAYOUT_STEREO;
+ device_info.device.input.sample_rate = sample_rate;
+ device_info.device.input.channel_layout = media::CHANNEL_LAYOUT_STEREO;
}
}
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 91413710020..a67237a1ed9 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
@@ -50,6 +50,7 @@ class MockAudioManager : public AudioManagerPlatform {
virtual void GetAudioInputDeviceNames(
media::AudioDeviceNames* device_names) OVERRIDE {
+ DCHECK(device_names->empty());
if (HasAudioInputDevices()) {
AudioManagerBase::GetAudioInputDeviceNames(device_names);
} else {
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 8ecbabcd47d..53f5a769313 100644
--- a/chromium/content/browser/renderer_host/media/midi_dispatcher_host.cc
+++ b/chromium/content/browser/renderer_host/media/midi_dispatcher_host.cc
@@ -5,6 +5,7 @@
#include "content/browser/renderer_host/media/midi_dispatcher_host.h"
#include "base/bind.h"
+#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/common/media/midi_messages.h"
#include "content/public/browser/browser_context.h"
@@ -57,6 +58,8 @@ void MIDIDispatcherHost::OnRequestSysExPermission(int render_view_id,
void MIDIDispatcherHost::WasSysExPermissionGranted(int render_view_id,
int client_id,
bool success) {
+ ChildProcessSecurityPolicyImpl::GetInstance()->GrantSendMIDISysExMessage(
+ render_process_id_);
Send(new MIDIMsg_SysExPermissionApproved(render_view_id, client_id, success));
}
diff --git a/chromium/content/browser/renderer_host/media/midi_host.cc b/chromium/content/browser/renderer_host/media/midi_host.cc
index 6ed473afeff..0467404bda3 100644
--- a/chromium/content/browser/renderer_host/media/midi_host.cc
+++ b/chromium/content/browser/renderer_host/media/midi_host.cc
@@ -9,10 +9,12 @@
#include "base/debug/trace_event.h"
#include "base/process/process.h"
#include "content/browser/browser_main_loop.h"
+#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/media/media_internals.h"
#include "content/common/media/midi_messages.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/media_observer.h"
+#include "content/public/browser/user_metrics.h"
#include "media/midi/midi_manager.h"
using media::MIDIManager;
@@ -32,8 +34,9 @@ static const uint8 kSysExMessage = 0xf0;
namespace content {
-MIDIHost::MIDIHost(media::MIDIManager* midi_manager)
- : midi_manager_(midi_manager),
+MIDIHost::MIDIHost(int renderer_process_id, media::MIDIManager* midi_manager)
+ : renderer_process_id_(renderer_process_id),
+ midi_manager_(midi_manager),
sent_bytes_in_flight_(0),
bytes_sent_since_last_acknowledgement_(0) {
}
@@ -88,12 +91,15 @@ void MIDIHost::OnStartSession(int client_id) {
output_ports));
}
-void MIDIHost::OnSendData(int port,
+void MIDIHost::OnSendData(uint32 port,
const std::vector<uint8>& data,
double timestamp) {
if (!midi_manager_)
return;
+ if (data.empty())
+ return;
+
base::AutoLock auto_lock(in_flight_lock_);
// Sanity check that we won't send too much.
@@ -102,47 +108,48 @@ void MIDIHost::OnSendData(int port,
data.size() + sent_bytes_in_flight_ > kMaxInFlightBytes)
return;
- // For now disallow all System Exclusive messages even if we
- // have permission.
- // TODO(toyoshim): allow System Exclusive if browser has granted
- // this client access. We'll likely need to pass a GURL
- // here to compare against our permissions.
- if (data.size() > 0 && data[0] >= kSysExMessage)
+ 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;
+ }
+ }
-#if defined(OS_ANDROID)
- // TODO(toyoshim): figure out why data() method does not compile on Android.
- NOTIMPLEMENTED();
-#else
midi_manager_->DispatchSendMIDIData(
this,
port,
- data.data(),
- data.size(),
+ data,
timestamp);
-#endif
sent_bytes_in_flight_ += data.size();
}
void MIDIHost::ReceiveMIDIData(
- int port_index,
+ uint32 port,
const uint8* data,
size_t length,
double timestamp) {
TRACE_EVENT0("midi", "MIDIHost::ReceiveMIDIData");
- // For now disallow all System Exclusive messages even if we
- // have permission.
- // TODO(toyoshim): allow System Exclusive if browser has granted
- // this client access. We'll likely need to pass a GURL
- // here to compare against our permissions.
- if (length > 0 && data[0] >= kSysExMessage)
+ // 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;
+ }
+ }
// Send to the renderer.
std::vector<uint8> v(data, data + length);
- Send(new MIDIMsg_DataReceived(port_index, v, timestamp));
+ Send(new MIDIMsg_DataReceived(port, v, timestamp));
}
void MIDIHost::AccumulateMIDIBytesSent(size_t n) {
diff --git a/chromium/content/browser/renderer_host/media/midi_host.h b/chromium/content/browser/renderer_host/media/midi_host.h
index f6b2813264e..944325d99a0 100644
--- a/chromium/content/browser/renderer_host/media/midi_host.h
+++ b/chromium/content/browser/renderer_host/media/midi_host.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_MIDI_HOST_H_
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_MIDI_HOST_H_
+#include <vector>
+
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
@@ -23,7 +25,7 @@ class CONTENT_EXPORT MIDIHost
public media::MIDIManagerClient {
public:
// Called from UI thread from the owner of this object.
- MIDIHost(media::MIDIManager* midi_manager);
+ MIDIHost(int renderer_process_id, media::MIDIManager* midi_manager);
// BrowserMessageFilter implementation.
virtual void OnChannelClosing() OVERRIDE;
@@ -33,7 +35,7 @@ class CONTENT_EXPORT MIDIHost
// MIDIManagerClient implementation.
virtual void ReceiveMIDIData(
- int port_index,
+ uint32 port,
const uint8* data,
size_t length,
double timestamp) OVERRIDE;
@@ -43,7 +45,7 @@ class CONTENT_EXPORT MIDIHost
void OnStartSession(int client_id);
// Data to be sent to a MIDI output port.
- void OnSendData(int port,
+ void OnSendData(uint32 port,
const std::vector<uint8>& data,
double timestamp);
@@ -53,6 +55,8 @@ class CONTENT_EXPORT MIDIHost
virtual ~MIDIHost();
+ int renderer_process_id_;
+
// |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
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 fc3734744ea..5f7fb847b3c 100644
--- a/chromium/content/browser/renderer_host/media/mock_media_observer.h
+++ b/chromium/content/browser/renderer_host/media/mock_media_observer.h
@@ -10,6 +10,7 @@
#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"
#include "testing/gmock/include/gmock/gmock.h"
@@ -47,6 +48,10 @@ class MockMediaInternals : public MediaInternals {
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,
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 207f86a99f3..3e30834feb2 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
@@ -128,8 +128,12 @@ int VideoCaptureBufferPool::RecognizeReservedBuffer(
scoped_refptr<media::VideoFrame> VideoCaptureBufferPool::ReserveI420VideoFrame(
const gfx::Size& size,
int rotation) {
- if (static_cast<size_t>(size.GetArea() * 3 / 2) != GetMemorySize())
+ 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_);
@@ -151,6 +155,7 @@ scoped_refptr<media::VideoFrame> VideoCaptureBufferPool::ReserveI420VideoFrame(
gfx::Rect(size),
size,
static_cast<uint8*>(buffer->shared_memory.memory()),
+ GetMemorySize(),
buffer->shared_memory.handle(),
base::TimeDelta(),
disposal_handler);
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 67a8be4c761..30509a34c75 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
@@ -21,8 +21,8 @@ TEST(VideoCaptureBufferPoolTest, BufferPool) {
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(size.GetArea() * 3 / 2, 3);
+ scoped_refptr<VideoCaptureBufferPool> pool = new VideoCaptureBufferPool(
+ media::VideoFrame::AllocationSize(media::VideoFrame::I420, size), 3);
ASSERT_EQ(460800u, pool->GetMemorySize());
ASSERT_TRUE(pool->Allocate());
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 bac43289a21..687a21a4996 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller.cc
@@ -7,6 +7,7 @@
#include <set>
#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"
@@ -22,6 +23,7 @@
namespace {
+#if defined(OS_IOS) || defined(OS_ANDROID)
// TODO(wjia): Support stride.
void RotatePackedYV12Frame(
const uint8* src,
@@ -43,6 +45,7 @@ void RotatePackedYV12Frame(
media::RotatePlaneByPixels(
src, dest_vplane, width/2, height/2, rotation, flip_vert, flip_horiz);
}
+#endif // #if defined(OS_IOS) || defined(OS_ANDROID)
} // namespace
@@ -77,31 +80,109 @@ struct VideoCaptureController::ControllerClient {
// Buffers used by this client.
std::set<int> buffers;
- // State of capture session, controlled by VideoCaptureManager directly.
+ // State of capture session, controlled by VideoCaptureManager directly. This
+ // transitions to true as soon as StopSession() occurs, at which point the
+ // client is sent an OnEnded() event. However, because the client retains a
+ // VideoCaptureController* pointer, its ControllerClient entry lives on until
+ // it unregisters itself via RemoveClient(), which may happen asynchronously.
+ //
+ // TODO(nick): If we changed the semantics of VideoCaptureHost so that
+ // OnEnded() events were processed synchronously (with the RemoveClient() done
+ // implicitly), we could avoid tracking this state here in the Controller, and
+ // simplify the code in both places.
bool session_closed;
};
-VideoCaptureController::VideoCaptureController(
- VideoCaptureManager* video_capture_manager)
- : chopped_width_(0),
- chopped_height_(0),
- frame_info_available_(false),
- video_capture_manager_(video_capture_manager),
- device_in_use_(false),
- state_(VIDEO_CAPTURE_STATE_STOPPED) {
+// Receives events from the VideoCaptureDevice and posts them to a
+// VideoCaptureController on the IO thread. An instance of this class may safely
+// outlive its target VideoCaptureController.
+//
+// Methods of this class may be called from any thread, and in practice will
+// often be called on some auxiliary thread depending on the platform and the
+// 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:
+ explicit VideoCaptureDeviceClient(
+ const base::WeakPtr<VideoCaptureController>& controller);
+ virtual ~VideoCaptureDeviceClient();
+
+ // VideoCaptureDevice::EventHandler implementation.
+ virtual scoped_refptr<media::VideoFrame> ReserveOutputBuffer() 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;
+ virtual void OnError() OVERRIDE;
+ virtual void OnFrameInfo(
+ const media::VideoCaptureCapability& info) OVERRIDE;
+ virtual void OnFrameInfoChanged(
+ const media::VideoCaptureCapability& info) OVERRIDE;
+
+ private:
+ // 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)
+};
+
+VideoCaptureController::VideoCaptureController()
+ : state_(VIDEO_CAPTURE_STATE_STARTED),
+ weak_ptr_factory_(this) {
memset(&current_params_, 0, sizeof(current_params_));
}
-void VideoCaptureController::StartCapture(
+VideoCaptureController::VideoCaptureDeviceClient::VideoCaptureDeviceClient(
+ const base::WeakPtr<VideoCaptureController>& controller)
+ : controller_(controller),
+ chopped_width_(0),
+ chopped_height_(0) {}
+
+VideoCaptureController::VideoCaptureDeviceClient::~VideoCaptureDeviceClient() {}
+
+base::WeakPtr<VideoCaptureController> VideoCaptureController::GetWeakPtr() {
+ return weak_ptr_factory_.GetWeakPtr();
+}
+
+scoped_ptr<media::VideoCaptureDevice::EventHandler>
+VideoCaptureController::NewDeviceClient() {
+ scoped_ptr<media::VideoCaptureDevice::EventHandler> result(
+ new VideoCaptureDeviceClient(this->GetWeakPtr()));
+ return result.Pass();
+}
+
+void VideoCaptureController::AddClient(
const VideoCaptureControllerID& id,
VideoCaptureControllerEventHandler* event_handler,
base::ProcessHandle render_process,
const media::VideoCaptureParams& params) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DVLOG(1) << "VideoCaptureController::StartCapture, id " << id.device_id
+ DVLOG(1) << "VideoCaptureController::AddClient, id " << id.device_id
<< ", (" << params.width
<< ", " << params.height
- << ", " << params.frame_per_second
+ << ", " << params.frame_rate
<< ", " << params.session_id
<< ")";
@@ -111,71 +192,32 @@ void VideoCaptureController::StartCapture(
return;
}
- // Do nothing if this client has called StartCapture before.
- if (FindClient(id, event_handler, controller_clients_) ||
- FindClient(id, event_handler, pending_clients_))
+ // Do nothing if this client has called AddClient before.
+ if (FindClient(id, event_handler, controller_clients_))
return;
ControllerClient* client = new ControllerClient(id, event_handler,
render_process, params);
- // In case capture has been started, need to check different conditions.
+ // If we already have gotten frame_info from the device, repeat it to the new
+ // client.
if (state_ == VIDEO_CAPTURE_STATE_STARTED) {
- // TODO(wjia): Temporarily disable restarting till client supports resampling.
-#if 0
- // This client has higher resolution than what is currently requested.
- // Need restart capturing.
- if (params.width > current_params_.width ||
- params.height > current_params_.height) {
- video_capture_manager_->Stop(current_params_.session_id,
- base::Bind(&VideoCaptureController::OnDeviceStopped, this));
- frame_info_available_ = false;
- state_ = VIDEO_CAPTURE_STATE_STOPPING;
- pending_clients_.push_back(client);
- return;
- }
-#endif
-
- // This client's resolution is no larger than what's currently requested.
- // When frame_info has been returned by device, send them to client.
- if (frame_info_available_) {
+ if (frame_info_.IsValid()) {
SendFrameInfoAndBuffers(client);
}
controller_clients_.push_back(client);
return;
}
-
- // In case the device is in the middle of stopping, put the client in
- // pending queue.
- if (state_ == VIDEO_CAPTURE_STATE_STOPPING) {
- pending_clients_.push_back(client);
- return;
- }
-
- // Fresh start.
- controller_clients_.push_back(client);
- current_params_ = params;
- // Order the manager to start the actual capture.
- video_capture_manager_->Start(params, this);
- state_ = VIDEO_CAPTURE_STATE_STARTED;
- device_in_use_ = true;
}
-void VideoCaptureController::StopCapture(
+int VideoCaptureController::RemoveClient(
const VideoCaptureControllerID& id,
VideoCaptureControllerEventHandler* event_handler) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DVLOG(1) << "VideoCaptureController::StopCapture, id " << id.device_id;
+ DVLOG(1) << "VideoCaptureController::RemoveClient, id " << id.device_id;
- ControllerClient* client = FindClient(id, event_handler, pending_clients_);
- // If the client is still in pending queue, just remove it.
- if (client) {
- pending_clients_.remove(client);
- return;
- }
-
- client = FindClient(id, event_handler, controller_clients_);
+ ControllerClient* client = FindClient(id, event_handler, controller_clients_);
if (!client)
- return;
+ return kInvalidMediaCaptureSessionId;
// Take back all buffers held by the |client|.
if (buffer_pool_.get()) {
@@ -189,28 +231,17 @@ void VideoCaptureController::StopCapture(
client->buffers.clear();
int session_id = client->parameters.session_id;
- delete client;
controller_clients_.remove(client);
+ delete client;
- // No more clients. Stop device.
- if (controller_clients_.empty() &&
- (state_ == VIDEO_CAPTURE_STATE_STARTED ||
- state_ == VIDEO_CAPTURE_STATE_ERROR)) {
- video_capture_manager_->Stop(session_id,
- base::Bind(&VideoCaptureController::OnDeviceStopped, this));
- frame_info_available_ = false;
- state_ = VIDEO_CAPTURE_STATE_STOPPING;
- }
+ return session_id;
}
-void VideoCaptureController::StopSession(
- int session_id) {
+void VideoCaptureController::StopSession(int session_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DVLOG(1) << "VideoCaptureController::StopSession, id " << session_id;
- ControllerClient* client = FindClient(session_id, pending_clients_);
- if (!client)
- client = FindClient(session_id, controller_clients_);
+ ControllerClient* client = FindClient(session_id, controller_clients_);
if (client) {
client->session_closed = true;
@@ -224,59 +255,174 @@ void VideoCaptureController::ReturnBuffer(
int buffer_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- ControllerClient* client = FindClient(id, event_handler,
- controller_clients_);
+ ControllerClient* client = FindClient(id, event_handler, controller_clients_);
// 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())
+ client->buffers.find(buffer_id) == client->buffers.end()) {
+ NOTREACHED();
return;
+ }
client->buffers.erase(buffer_id);
buffer_pool_->RelinquishConsumerHold(buffer_id, 1);
-
- // When all buffers have been returned by clients and device has been
- // called to stop, check if restart is needed. This could happen when
- // capture needs to be restarted due to resolution change.
- if (!buffer_pool_->IsAnyBufferHeldForConsumers() &&
- state_ == VIDEO_CAPTURE_STATE_STOPPING) {
- PostStopping();
- }
}
-scoped_refptr<media::VideoFrame> VideoCaptureController::ReserveOutputBuffer() {
- base::AutoLock lock(buffer_pool_lock_);
- if (!buffer_pool_.get())
- return NULL;
+scoped_refptr<media::VideoFrame>
+VideoCaptureController::VideoCaptureDeviceClient::ReserveOutputBuffer() {
return buffer_pool_->ReserveI420VideoFrame(gfx::Size(frame_info_.width,
frame_info_.height),
0);
}
-// Implements VideoCaptureDevice::EventHandler.
-// OnIncomingCapturedFrame is called the thread running the capture device.
-// I.e.- DirectShow thread on windows and v4l2_thread on Linux.
-void VideoCaptureController::OnIncomingCapturedFrame(
+#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) {
- DCHECK(frame_info_.color == media::VideoCaptureCapability::kI420 ||
- frame_info_.color == media::VideoCaptureCapability::kYV12 ||
- (rotation == 0 && !flip_vert && !flip_horiz));
+ TRACE_EVENT0("video", "VideoCaptureController::OnIncomingCapturedFrame");
- scoped_refptr<media::VideoFrame> dst;
- {
- base::AutoLock lock(buffer_pool_lock_);
- if (!buffer_pool_.get())
- return;
- dst = buffer_pool_->ReserveI420VideoFrame(gfx::Size(frame_info_.width,
- frame_info_.height),
- rotation);
+ if (!buffer_pool_.get())
+ 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);
+ int yplane_stride = frame_info_.width;
+ int uv_plane_stride = (frame_info_.width + 1) / 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)
+ rotation_mode = libyuv::kRotate90;
+ else if (new_rotation_angle == 180)
+ rotation_mode = libyuv::kRotate180;
+ else if (new_rotation_angle == 270)
+ rotation_mode = libyuv::kRotate270;
+
+ switch (frame_info_.color) {
+ case media::PIXEL_FORMAT_UNKNOWN: // Color format not set.
+ break;
+ case media::PIXEL_FORMAT_I420:
+ DCHECK(!chopped_width_ && !chopped_height_);
+ origin_colorspace = libyuv::FOURCC_I420;
+ break;
+ case media::PIXEL_FORMAT_YV12:
+ 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;
+ break;
+ case media::PIXEL_FORMAT_YUY2:
+ DCHECK(!chopped_width_ && !chopped_height_);
+ origin_colorspace = libyuv::FOURCC_YUY2;
+ break;
+ case media::PIXEL_FORMAT_UYVY:
+ DCHECK(!chopped_width_ && !chopped_height_);
+ origin_colorspace = libyuv::FOURCC_UYVY;
+ break;
+ case media::PIXEL_FORMAT_RGB24:
+ origin_colorspace = libyuv::FOURCC_RAW;
+ break;
+ case media::PIXEL_FORMAT_ARGB:
+ origin_colorspace = libyuv::FOURCC_ARGB;
+ break;
+ case media::PIXEL_FORMAT_MJPEG:
+ origin_colorspace = libyuv::FOURCC_MJPG;
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ 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);
+ need_convert_rgb24_on_win = true;
}
+#endif
+ if (need_convert_rgb24_on_win) {
+ int rgb_stride = -3 * (frame_info_.width + chopped_width_);
+ const uint8* rgb_src =
+ data + 3 * (frame_info_.width + chopped_width_) *
+ (frame_info_.height - 1 + chopped_height_);
+ media::ConvertRGB24ToYUV(rgb_src,
+ yplane,
+ uplane,
+ vplane,
+ frame_info_.width,
+ frame_info_.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);
+ }
+ 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;
@@ -287,26 +433,36 @@ void VideoCaptureController::OnIncomingCapturedFrame(
// Do color conversion from the camera format to I420.
switch (frame_info_.color) {
- case media::VideoCaptureCapability::kColorUnknown: // Color format not set.
+ case media::PIXEL_FORMAT_UNKNOWN: // Color format not set.
break;
- case media::VideoCaptureCapability::kI420:
+ 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::VideoCaptureCapability::kYV12:
+ 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::VideoCaptureCapability::kNV21:
+ case media::PIXEL_FORMAT_NV21: {
DCHECK(!chopped_width_ && !chopped_height_);
- media::ConvertNV21ToYUV(data, yplane, uplane, vplane, frame_info_.width,
+ 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);
- break;
- case media::VideoCaptureCapability::kYUY2:
+ 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
@@ -317,42 +473,22 @@ void VideoCaptureController::OnIncomingCapturedFrame(
media::ConvertYUY2ToYUV(data, yplane, uplane, vplane, frame_info_.width,
frame_info_.height);
break;
- case media::VideoCaptureCapability::kRGB24: {
+ case media::PIXEL_FORMAT_RGB24: {
int ystride = frame_info_.width;
int uvstride = frame_info_.width / 2;
-#if defined(OS_WIN) // RGB on Windows start at the bottom line.
- int rgb_stride = -3 * (frame_info_.width + chopped_width_);
- const uint8* rgb_src = data + 3 * (frame_info_.width + chopped_width_) *
- (frame_info_.height -1 + chopped_height_);
-#else
int rgb_stride = 3 * (frame_info_.width + chopped_width_);
const uint8* rgb_src = data;
-#endif
media::ConvertRGB24ToYUV(rgb_src, yplane, uplane, vplane,
frame_info_.width, frame_info_.height,
rgb_stride, ystride, uvstride);
break;
}
- case media::VideoCaptureCapability::kARGB:
+ 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;
-#if !defined(OS_IOS) && !defined(OS_ANDROID)
- case media::VideoCaptureCapability::kMJPEG: {
- int yplane_stride = frame_info_.width;
- int uv_plane_stride = (frame_info_.width + 1) / 2;
- int crop_x = 0;
- int crop_y = 0;
- libyuv::ConvertToI420(data, length, yplane, yplane_stride, uplane,
- uv_plane_stride, vplane, uv_plane_stride, crop_x,
- crop_y, frame_info_.width, frame_info_.height,
- frame_info_.width, frame_info_.height,
- libyuv::kRotate0, libyuv::FOURCC_MJPG);
- break;
- }
-#endif
default:
NOTREACHED();
}
@@ -360,38 +496,35 @@ void VideoCaptureController::OnIncomingCapturedFrame(
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
- this, dst, timestamp));
+ controller_, dst, timestamp));
}
+#endif // #if !defined(OS_IOS) && !defined(OS_ANDROID)
-// OnIncomingCapturedVideoFrame is called the thread running the capture device.
-void VideoCaptureController::OnIncomingCapturedVideoFrame(
+void
+VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame(
const scoped_refptr<media::VideoFrame>& frame,
base::Time timestamp) {
+ if (!buffer_pool_)
+ return;
- scoped_refptr<media::VideoFrame> target;
- {
- base::AutoLock lock(buffer_pool_lock_);
-
- if (!buffer_pool_.get())
- 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,
- this, 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.
- target = buffer_pool_->ReserveI420VideoFrame(gfx::Size(frame_info_.width,
- frame_info_.height),
- 0);
+ // 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;
@@ -478,18 +611,18 @@ void VideoCaptureController::OnIncomingCapturedVideoFrame(
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
- this, target, timestamp));
+ controller_, target, timestamp));
}
-void VideoCaptureController::OnError() {
+void VideoCaptureController::VideoCaptureDeviceClient::OnError() {
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
- base::Bind(&VideoCaptureController::DoErrorOnIOThread, this));
+ base::Bind(&VideoCaptureController::DoErrorOnIOThread, controller_));
}
-void VideoCaptureController::OnFrameInfo(
+void VideoCaptureController::VideoCaptureDeviceClient::OnFrameInfo(
const media::VideoCaptureCapability& info) {
- frame_info_= info;
+ frame_info_ = info;
// Handle cases when |info| has odd numbers for width/height.
if (info.width & 1) {
--frame_info_.width;
@@ -503,32 +636,51 @@ void VideoCaptureController::OnFrameInfo(
} 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;
+ }
+
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
- base::Bind(&VideoCaptureController::DoFrameInfoOnIOThread, this));
+ base::Bind(&VideoCaptureController::DoFrameInfoOnIOThread, controller_,
+ frame_info_, buffer_pool_));
}
-void VideoCaptureController::OnFrameInfoChanged(
+void VideoCaptureController::VideoCaptureDeviceClient::OnFrameInfoChanged(
const media::VideoCaptureCapability& info) {
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
base::Bind(&VideoCaptureController::DoFrameInfoChangedOnIOThread,
- this, info));
+ controller_, info));
}
VideoCaptureController::~VideoCaptureController() {
buffer_pool_ = NULL; // Release all buffers.
STLDeleteContainerPointers(controller_clients_.begin(),
controller_clients_.end());
- STLDeleteContainerPointers(pending_clients_.begin(),
- pending_clients_.end());
-}
-
-// Called by VideoCaptureManager when a device have been stopped.
-void VideoCaptureController::OnDeviceStopped() {
- BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(&VideoCaptureController::DoDeviceStoppedOnIOThread, this));
}
void VideoCaptureController::DoIncomingCapturedFrameOnIOThread(
@@ -563,37 +715,24 @@ void VideoCaptureController::DoIncomingCapturedFrameOnIOThread(
buffer_pool_->HoldForConsumers(buffer_id, count);
}
-void VideoCaptureController::DoFrameInfoOnIOThread() {
+void VideoCaptureController::DoFrameInfoOnIOThread(
+ const media::VideoCaptureCapability& frame_info,
+ const scoped_refptr<VideoCaptureBufferPool>& buffer_pool) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DCHECK(!buffer_pool_.get())
- << "Device is restarted without releasing shared memory.";
+ 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;
- scoped_refptr<VideoCaptureBufferPool> buffer_pool =
- new VideoCaptureBufferPool(frame_info_.width * frame_info_.height * 3 / 2,
- kNoOfBuffers);
-
- // Check whether all buffers were created successfully.
- if (!buffer_pool->Allocate()) {
- state_ = VIDEO_CAPTURE_STATE_ERROR;
- for (ControllerClients::iterator client_it = controller_clients_.begin();
- client_it != controller_clients_.end(); ++client_it) {
- (*client_it)->event_handler->OnError((*client_it)->controller_id);
- }
- return;
- }
-
- {
- base::AutoLock lock(buffer_pool_lock_);
- buffer_pool_ = buffer_pool;
- }
- frame_info_available_ = true;
+ frame_info_ = frame_info;
+ buffer_pool_ = buffer_pool;
for (ControllerClients::iterator client_it = controller_clients_.begin();
client_it != controller_clients_.end(); ++client_it) {
+ if ((*client_it)->session_closed)
+ continue;
+
SendFrameInfoAndBuffers(*client_it);
}
}
@@ -605,6 +744,9 @@ void VideoCaptureController::DoFrameInfoChangedOnIOThread(
// 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,
@@ -619,25 +761,16 @@ void VideoCaptureController::DoErrorOnIOThread() {
ControllerClients::iterator client_it;
for (client_it = controller_clients_.begin();
client_it != controller_clients_.end(); ++client_it) {
- (*client_it)->event_handler->OnError((*client_it)->controller_id);
- }
- for (client_it = pending_clients_.begin();
- client_it != pending_clients_.end(); ++client_it) {
- (*client_it)->event_handler->OnError((*client_it)->controller_id);
- }
-}
+ if ((*client_it)->session_closed)
+ continue;
-void VideoCaptureController::DoDeviceStoppedOnIOThread() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- device_in_use_ = false;
- if (state_ == VIDEO_CAPTURE_STATE_STOPPING) {
- PostStopping();
+ (*client_it)->event_handler->OnError((*client_it)->controller_id);
}
}
void VideoCaptureController::SendFrameInfoAndBuffers(ControllerClient* client) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DCHECK(frame_info_available_);
+ 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) {
@@ -679,54 +812,9 @@ VideoCaptureController::FindClient(
return NULL;
}
-// This function is called when all buffers have been returned to controller,
-// or when device is stopped. It decides whether the device needs to be
-// restarted.
-void VideoCaptureController::PostStopping() {
+int VideoCaptureController::GetClientCount() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DCHECK_EQ(state_, VIDEO_CAPTURE_STATE_STOPPING);
-
- // When clients still have some buffers, or device has not been stopped yet,
- // do nothing.
- if ((buffer_pool_.get() && buffer_pool_->IsAnyBufferHeldForConsumers()) ||
- device_in_use_)
- return;
-
- {
- base::AutoLock lock(buffer_pool_lock_);
- buffer_pool_ = NULL;
- }
-
- // No more client. Therefore the controller is stopped.
- if (controller_clients_.empty() && pending_clients_.empty()) {
- state_ = VIDEO_CAPTURE_STATE_STOPPED;
- return;
- }
-
- // Restart the device.
- current_params_.width = 0;
- current_params_.height = 0;
- ControllerClients::iterator client_it;
- for (client_it = controller_clients_.begin();
- client_it != controller_clients_.end(); ++client_it) {
- if (current_params_.width < (*client_it)->parameters.width)
- current_params_.width = (*client_it)->parameters.width;
- if (current_params_.height < (*client_it)->parameters.height)
- current_params_.height = (*client_it)->parameters.height;
- }
- for (client_it = pending_clients_.begin();
- client_it != pending_clients_.end(); ) {
- if (current_params_.width < (*client_it)->parameters.width)
- current_params_.width = (*client_it)->parameters.width;
- if (current_params_.height < (*client_it)->parameters.height)
- current_params_.height = (*client_it)->parameters.height;
- controller_clients_.push_back((*client_it));
- pending_clients_.erase(client_it++);
- }
- // Request the manager to start the actual capture.
- video_capture_manager_->Start(current_params_, this);
- state_ = VIDEO_CAPTURE_STATE_STARTED;
- device_in_use_ = true;
+ return controller_clients_.size();
}
} // namespace content
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 5d33d01163c..eda4ce31e01 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller.h
@@ -1,17 +1,48 @@
// 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.
-
-// VideoCaptureController is the glue between VideoCaptureHost,
-// VideoCaptureManager and VideoCaptureDevice.
-// It provides functions for VideoCaptureHost to start a VideoCaptureDevice and
-// is responsible for keeping track of shared DIBs and filling them with I420
-// video frames for IPC communication between VideoCaptureHost and
-// VideoCaptureMessageFilter.
-// It implements media::VideoCaptureDevice::EventHandler to get video frames
-// from a VideoCaptureDevice object and do color conversion straight into the
-// shared DIBs to avoid a memory copy.
-// It serves multiple VideoCaptureControllerEventHandlers.
+//
+// VideoCaptureController is the glue between a VideoCaptureDevice and all
+// VideoCaptureHosts that have connected to it. A controller exists on behalf of
+// one (and only one) VideoCaptureDevice; both are owned by the
+// VideoCaptureManager.
+//
+// The VideoCaptureController is responsible for:
+//
+// * Allocating and keeping track of shared memory buffers, and filling them
+// with I420 video frames for IPC communication between VideoCaptureHost (in
+// the browser process) and VideoCaptureMessageFilter (in the renderer
+// process).
+// * Broadcasting the events from a single VideoCaptureDevice, fanning them
+// out to multiple clients.
+// * Keeping track of the clients on behalf of the VideoCaptureManager, making
+// it possible for the Manager to delete the Controller and its Device when
+// there are no clients left.
+//
+// A helper class, VCC::VideoCaptureDeviceClient, is responsible for:
+//
+// * Conveying events from the device thread (where VideoCaptureDevices live)
+// the IO thread (where the VideoCaptureController lives).
+// * Performing some image transformations on the output of the Device;
+// specifically, colorspace conversion and rotation.
+//
+// Interactions between VideoCaptureController and other classes:
+//
+// * VideoCaptureController indirectly observes a VideoCaptureDevice
+// by means of its proxy, VideoCaptureDeviceClient, which implements
+// the VideoCaptureDevice::EventHandler interface. The proxy forwards
+// observed events to the VideoCaptureController on the IO thread.
+// * A VideoCaptureController interacts with its clients (VideoCaptureHosts)
+// via the VideoCaptureControllerEventHandler interface.
+// * Conversely, a VideoCaptureControllerEventHandler (typically,
+// VideoCaptureHost) will interact directly with VideoCaptureController to
+// return leased buffers by means of the ReturnBuffer() public method of
+// VCC.
+// * VideoCaptureManager (which owns the VCC) interacts directly with
+// VideoCaptureController through its public methods, to add and remove
+// clients.
+//
+// VideoCaptureController is not thread safe and operates on the IO thread only.
#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_CONTROLLER_H_
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_CONTROLLER_H_
@@ -21,6 +52,8 @@
#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"
@@ -32,31 +65,37 @@
#include "media/video/capture/video_capture_types.h"
namespace content {
-class VideoCaptureManager;
class VideoCaptureBufferPool;
-class CONTENT_EXPORT VideoCaptureController
- : public base::RefCountedThreadSafe<VideoCaptureController>,
- public media::VideoCaptureDevice::EventHandler {
+class CONTENT_EXPORT VideoCaptureController {
public:
- VideoCaptureController(VideoCaptureManager* video_capture_manager);
+ VideoCaptureController();
+ virtual ~VideoCaptureController();
+
+ base::WeakPtr<VideoCaptureController> GetWeakPtr();
+
+ // Return a new VideoCaptureDeviceClient to forward capture events to this
+ // instance.
+ scoped_ptr<media::VideoCaptureDevice::EventHandler> NewDeviceClient();
// Start video capturing and try to use the resolution specified in
// |params|.
- // When capturing has started, the |event_handler| receives a call OnFrameInfo
- // with resolution that best matches the requested that the video
- // capture device support.
- void StartCapture(const VideoCaptureControllerID& id,
- VideoCaptureControllerEventHandler* event_handler,
- base::ProcessHandle render_process,
- const media::VideoCaptureParams& params);
-
- // Stop video capture.
- // This will take back all buffers held by by |event_handler|, and
- // |event_handler| shouldn't use those buffers any more.
- void StopCapture(const VideoCaptureControllerID& id,
+ // When capturing starts, the |event_handler| will receive an OnFrameInfo()
+ // call informing it of the resolution that was actually picked by the device.
+ void AddClient(const VideoCaptureControllerID& id,
+ VideoCaptureControllerEventHandler* event_handler,
+ base::ProcessHandle render_process,
+ const media::VideoCaptureParams& params);
+
+ // Stop video capture. This will take back all buffers held by by
+ // |event_handler|, and |event_handler| shouldn't use those buffers any more.
+ // Returns the session_id of the stopped client, or
+ // kInvalidMediaCaptureSessionId if the indicated client was not registered.
+ int RemoveClient(const VideoCaptureControllerID& id,
VideoCaptureControllerEventHandler* event_handler);
+ int GetClientCount();
+
// API called directly by VideoCaptureManager in case the device is
// prematurely closed.
void StopSession(int session_id);
@@ -67,39 +106,19 @@ class CONTENT_EXPORT VideoCaptureController
VideoCaptureControllerEventHandler* event_handler,
int buffer_id);
- // Implement media::VideoCaptureDevice::EventHandler.
- virtual scoped_refptr<media::VideoFrame> ReserveOutputBuffer() 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;
- virtual void OnError() OVERRIDE;
- virtual void OnFrameInfo(const media::VideoCaptureCapability& info) OVERRIDE;
- virtual void OnFrameInfoChanged(
- const media::VideoCaptureCapability& info) OVERRIDE;
-
- protected:
- virtual ~VideoCaptureController();
-
private:
- friend class base::RefCountedThreadSafe<VideoCaptureController>;
+ class VideoCaptureDeviceClient;
struct ControllerClient;
typedef std::list<ControllerClient*> ControllerClients;
- // Callback when manager has stopped device.
- void OnDeviceStopped();
-
- // Worker functions on IO thread.
+ // Worker functions on IO thread. Called by the VideoCaptureDeviceClient.
void DoIncomingCapturedFrameOnIOThread(
const scoped_refptr<media::VideoFrame>& captured_frame,
base::Time timestamp);
- void DoFrameInfoOnIOThread();
+ void DoFrameInfoOnIOThread(
+ const media::VideoCaptureCapability& frame_info,
+ const scoped_refptr<VideoCaptureBufferPool>& buffer_pool);
void DoFrameInfoChangedOnIOThread(const media::VideoCaptureCapability& info);
void DoErrorOnIOThread();
void DoDeviceStoppedOnIOThread();
@@ -118,45 +137,25 @@ class CONTENT_EXPORT VideoCaptureController
int session_id,
const ControllerClients& clients);
- // Decide what to do after kStopping state. Dependent on events, controller
- // can stay in kStopping state, or go to kStopped, or restart capture.
- void PostStopping();
-
- // Protects access to the |buffer_pool_| pointer on non-IO threads. IO thread
- // must hold this lock when modifying the |buffer_pool_| pointer itself.
- // TODO(nick): Make it so that this lock isn't required.
- base::Lock buffer_pool_lock_;
-
// The pool of shared-memory buffers used for capturing.
scoped_refptr<VideoCaptureBufferPool> buffer_pool_;
// All clients served by this controller.
ControllerClients controller_clients_;
- // All clients waiting for service.
- ControllerClients pending_clients_;
-
// The parameter that currently used for the capturing.
media::VideoCaptureParams current_params_;
- // It's modified on caller thread, assuming there is only one OnFrameInfo()
- // call per StartCapture().
+ // Tracks the current frame format.
media::VideoCaptureCapability frame_info_;
- // Chopped pixels in width/height in case video capture device has odd numbers
- // for width/height.
- int chopped_width_;
- int chopped_height_;
-
- // It's accessed only on IO thread.
- bool frame_info_available_;
-
- VideoCaptureManager* video_capture_manager_;
-
- bool device_in_use_;
+ // Takes on only the states 'STARTED' and 'ERROR'. 'ERROR' is an absorbing
+ // state which stops the flow of data to clients.
VideoCaptureState state_;
- DISALLOW_IMPLICIT_CONSTRUCTORS(VideoCaptureController);
+ base::WeakPtrFactory<VideoCaptureController> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(VideoCaptureController);
};
} // namespace content
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 c4844af2f73..4a2c294b0ba 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
@@ -10,7 +10,7 @@
#include "content/common/content_export.h"
namespace media {
-struct VideoCaptureCapability;
+class VideoCaptureCapability;
}
namespace content {
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 c4b716d2e33..fec0942dde0 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
@@ -7,141 +7,74 @@
#include <string>
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
-#include "content/browser/browser_thread_impl.h"
+#include "base/run_loop.h"
#include "content/browser/renderer_host/media/media_stream_provider.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/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 "content/public/test/test_browser_thread_bundle.h"
+#include "media/base/video_frame.h"
+#include "media/base/video_util.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::AtLeast;
using ::testing::InSequence;
-using ::testing::Return;
+using ::testing::Mock;
namespace content {
-enum { kDeviceId = 1 };
-
-ACTION_P4(StopCapture, controller, controller_id, controller_handler,
- message_loop) {
- message_loop->PostTask(FROM_HERE,
- base::Bind(&VideoCaptureController::StopCapture,
- controller, controller_id, controller_handler));
- message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
-}
-
-ACTION_P3(StopSession, controller, session_id, message_loop) {
- message_loop->PostTask(FROM_HERE,
- base::Bind(&VideoCaptureController::StopSession,
- controller, session_id));
- message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
-}
-
class MockVideoCaptureControllerEventHandler
: public VideoCaptureControllerEventHandler {
public:
- MockVideoCaptureControllerEventHandler(VideoCaptureController* controller,
- base::MessageLoop* message_loop)
- : controller_(controller),
- message_loop_(message_loop),
- controller_id_(kDeviceId),
- process_handle_(base::kNullProcessHandle) {
- }
+ explicit MockVideoCaptureControllerEventHandler(
+ VideoCaptureController* controller)
+ : controller_(controller) {}
virtual ~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(DoBufferReady, void(const VideoCaptureControllerID&));
MOCK_METHOD1(DoFrameInfo, void(const VideoCaptureControllerID&));
MOCK_METHOD1(DoEnded, void(const VideoCaptureControllerID&));
+ MOCK_METHOD1(DoError, void(const VideoCaptureControllerID&));
- virtual void OnError(const VideoCaptureControllerID& id) OVERRIDE {}
+ virtual void OnError(const VideoCaptureControllerID& id) OVERRIDE {
+ DoError(id);
+ }
virtual void OnBufferCreated(const VideoCaptureControllerID& id,
base::SharedMemoryHandle handle,
int length, int buffer_id) OVERRIDE {
- EXPECT_EQ(id, controller_id_);
DoBufferCreated(id);
}
virtual void OnBufferReady(const VideoCaptureControllerID& id,
int buffer_id,
base::Time timestamp) OVERRIDE {
- EXPECT_EQ(id, controller_id_);
DoBufferReady(id);
- message_loop_->PostTask(FROM_HERE,
+ base::MessageLoop::current()->PostTask(FROM_HERE,
base::Bind(&VideoCaptureController::ReturnBuffer,
- controller_, controller_id_, this, buffer_id));
+ base::Unretained(controller_), id, this, buffer_id));
}
virtual void OnFrameInfo(
const VideoCaptureControllerID& id,
const media::VideoCaptureCapability& format) OVERRIDE {
- EXPECT_EQ(id, controller_id_);
DoFrameInfo(id);
}
virtual void OnEnded(const VideoCaptureControllerID& id) OVERRIDE {
- EXPECT_EQ(id, controller_id_);
DoEnded(id);
+ // OnEnded() must respond by (eventually) unregistering the client.
+ base::MessageLoop::current()->PostTask(FROM_HERE,
+ base::Bind(base::IgnoreResult(&VideoCaptureController::RemoveClient),
+ base::Unretained(controller_), id, this));
}
- scoped_refptr<VideoCaptureController> controller_;
- base::MessageLoop* message_loop_;
- VideoCaptureControllerID controller_id_;
- base::ProcessHandle process_handle_;
-};
-
-class MockVideoCaptureManager : public VideoCaptureManager {
- public:
- MockVideoCaptureManager()
- : video_session_id_(kStartOpenSessionId),
- device_name_("fake_device_0", "/dev/video0") {}
-
- void Init() {
- video_capture_device_.reset(
- media::FakeVideoCaptureDevice::Create(device_name_));
- ASSERT_TRUE(video_capture_device_.get() != NULL);
- }
-
- MOCK_METHOD3(StartCapture, void(int, int,
- media::VideoCaptureDevice::EventHandler*));
- MOCK_METHOD1(StopCapture, void(const media::VideoCaptureSessionId&));
-
- void Start(const media::VideoCaptureParams& capture_params,
- media::VideoCaptureDevice::EventHandler* vc_receiver) OVERRIDE {
- StartCapture(capture_params.width, capture_params.height, vc_receiver);
- // TODO(mcasas): Add testing for variable resolution video capture devices,
- // supported by FakeVideoCaptureDevice. See crbug.com/261410, second part.
- media::VideoCaptureCapability capture_format(
- capture_params.width,
- capture_params.height,
- capture_params.frame_per_second,
- media::VideoCaptureCapability::kI420,
- 0,
- false,
- media::ConstantResolutionVideoCaptureDevice);
- video_capture_device_->Allocate(capture_format, vc_receiver);
- video_capture_device_->Start();
- }
-
- void Stop(const media::VideoCaptureSessionId& capture_session_id,
- base::Closure stopped_cb) OVERRIDE {
- StopCapture(capture_session_id);
- video_capture_device_->Stop();
- video_capture_device_->DeAllocate();
- }
-
- int video_session_id_;
- media::VideoCaptureDevice::Name device_name_;
- scoped_ptr<media::VideoCaptureDevice> video_capture_device_;
-
- private:
- virtual ~MockVideoCaptureManager() {}
- DISALLOW_COPY_AND_ASSIGN(MockVideoCaptureManager);
+ VideoCaptureController* controller_;
};
// Test class.
@@ -151,115 +84,371 @@ class VideoCaptureControllerTest : public testing::Test {
virtual ~VideoCaptureControllerTest() {}
protected:
+ static const int kPoolSize = 3;
+
virtual void SetUp() OVERRIDE {
- message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_IO));
- file_thread_.reset(new BrowserThreadImpl(BrowserThread::FILE,
- message_loop_.get()));
- io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
- message_loop_.get()));
-
- vcm_ = new MockVideoCaptureManager();
- vcm_->Init();
- controller_ = new VideoCaptureController(vcm_.get());
- controller_handler_.reset(new MockVideoCaptureControllerEventHandler(
- controller_.get(), message_loop_.get()));
+ controller_.reset(new VideoCaptureController());
+ device_ = controller_->NewDeviceClient().Pass();
+ client_a_.reset(new MockVideoCaptureControllerEventHandler(
+ controller_.get()));
+ client_b_.reset(new MockVideoCaptureControllerEventHandler(
+ controller_.get()));
}
- virtual void TearDown() OVERRIDE {}
+ virtual void TearDown() OVERRIDE {
+ base::RunLoop().RunUntilIdle();
+ }
- scoped_ptr<base::MessageLoop> message_loop_;
- scoped_ptr<BrowserThreadImpl> file_thread_;
- scoped_ptr<BrowserThreadImpl> io_thread_;
- scoped_refptr<MockVideoCaptureManager> vcm_;
- scoped_ptr<MockVideoCaptureControllerEventHandler> controller_handler_;
- scoped_refptr<VideoCaptureController> controller_;
+ TestBrowserThreadBundle bindle_;
+ scoped_ptr<MockVideoCaptureControllerEventHandler> client_a_;
+ scoped_ptr<MockVideoCaptureControllerEventHandler> client_b_;
+ scoped_ptr<VideoCaptureController> controller_;
+ scoped_ptr<media::VideoCaptureDevice::EventHandler> device_;
private:
DISALLOW_COPY_AND_ASSIGN(VideoCaptureControllerTest);
};
-// Try to start and stop capture.
-TEST_F(VideoCaptureControllerTest, StartAndStop) {
- media::VideoCaptureParams capture_params;
- capture_params.session_id = vcm_->video_session_id_;
- capture_params.width = 320;
- capture_params.height = 240;
- capture_params.frame_per_second = 30;
-
- InSequence s;
- EXPECT_CALL(*vcm_.get(),
- StartCapture(capture_params.width,
- capture_params.height,
- controller_.get())).Times(1);
- EXPECT_CALL(*controller_handler_,
- DoFrameInfo(controller_handler_->controller_id_))
- .Times(AtLeast(1));
- EXPECT_CALL(*controller_handler_,
- DoBufferCreated(controller_handler_->controller_id_))
- .Times(AtLeast(1));
- EXPECT_CALL(*controller_handler_,
- DoBufferReady(controller_handler_->controller_id_))
- .Times(AtLeast(1))
- .WillOnce(StopCapture(controller_.get(),
- controller_handler_->controller_id_,
- controller_handler_.get(),
- message_loop_.get()));
- EXPECT_CALL(*vcm_.get(), StopCapture(vcm_->video_session_id_)).Times(1);
-
- controller_->StartCapture(controller_handler_->controller_id_,
- controller_handler_.get(),
- controller_handler_->process_handle_,
- capture_params);
- message_loop_->Run();
+// A simple test of VideoCaptureController's ability to add, remove, and keep
+// 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;
+
+ 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.
+ const VideoCaptureControllerID client_a_route_1(44);
+ const VideoCaptureControllerID client_a_route_2(30);
+ const VideoCaptureControllerID client_b_route_1(30);
+ const VideoCaptureControllerID client_b_route_2(1);
+
+ // 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);
+ // 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);
+ // 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);
+ // Clients in controller: [A/1, A/2, B/1]
+ ASSERT_EQ(3, controller_->GetClientCount())
+ << "Adding client B/1 should bump client count.";
+ ASSERT_EQ(200,
+ controller_->RemoveClient(client_a_route_2, client_a_.get()))
+ << "Removing client A/1 should return its session_id.";
+ // Clients in controller: [A/1, B/1]
+ ASSERT_EQ(2, controller_->GetClientCount());
+ ASSERT_EQ(static_cast<int>(kInvalidMediaCaptureSessionId),
+ controller_->RemoveClient(client_a_route_2, client_a_.get()))
+ << "Removing a nonexistant client should fail.";
+ // Clients in controller: [A/1, B/1]
+ ASSERT_EQ(2, controller_->GetClientCount());
+ ASSERT_EQ(300,
+ controller_->RemoveClient(client_b_route_1, client_b_.get()))
+ << "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);
+ // Clients in controller: [A/1, B/2]
+
+ EXPECT_CALL(*client_a_, DoEnded(client_a_route_1)).Times(1);
+ controller_->StopSession(100); // Session 100 == client A/1
+ Mock::VerifyAndClearExpectations(client_a_.get());
+ ASSERT_EQ(2, controller_->GetClientCount())
+ << "Client should be closed but still exist after StopSession.";
+ // Clients in controller: [A/1 (closed, removal pending), B/2]
+ base::RunLoop().RunUntilIdle();
+ // Clients in controller: [B/2]
+ ASSERT_EQ(1, controller_->GetClientCount())
+ << "Client A/1 should be deleted by now.";
+ controller_->StopSession(200); // Session 200 does not exist anymore
+ // Clients in controller: [B/2]
+ ASSERT_EQ(1, controller_->GetClientCount())
+ << "Stopping non-existant session 200 should be a no-op.";
+ controller_->StopSession(256); // Session 256 never existed.
+ // Clients in controller: [B/2]
+ ASSERT_EQ(1, controller_->GetClientCount())
+ << "Stopping non-existant session 256 should be a no-op.";
+ ASSERT_EQ(static_cast<int>(kInvalidMediaCaptureSessionId),
+ controller_->RemoveClient(client_a_route_1, client_a_.get()))
+ << "Removing already-removed client A/1 should fail.";
+ // Clients in controller: [B/2]
+ ASSERT_EQ(1, controller_->GetClientCount())
+ << "Removing non-existant session 200 should be a no-op.";
+ ASSERT_EQ(400,
+ controller_->RemoveClient(client_b_route_2, client_b_.get()))
+ << "Removing client B/2 should return its session_id.";
+ // Clients in controller: []
+ ASSERT_EQ(0, controller_->GetClientCount())
+ << "Client count should return to zero after all clients are gone.";
+}
+
+// This test will connect and disconnect several clients while simulating an
+// active capture device being started and generating frames. It runs on one
+// thread and is intended to behave deterministically.
+TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
+ media::VideoCaptureParams session_100;
+ session_100.session_id = 100;
+ session_100.width = 320;
+ session_100.height = 240;
+ session_100.frame_rate = 30;
+
+ 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;
+
+ // 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);
+
+ const VideoCaptureControllerID client_a_route_1(0xa1a1a1a1);
+ const VideoCaptureControllerID client_a_route_2(0xa2a2a2a2);
+ const VideoCaptureControllerID client_b_route_1(0xb1b1b1b1);
+ 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.
+ {
+ InSequence s;
+ EXPECT_CALL(*client_a_, DoFrameInfo(client_a_route_1)).Times(1);
+ EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1)).Times(kPoolSize);
+ }
+ {
+ InSequence s;
+ EXPECT_CALL(*client_b_, DoFrameInfo(client_b_route_1)).Times(1);
+ EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1)).Times(kPoolSize);
+ }
+ 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);
+ }
+ controller_->AddClient(client_a_route_2, client_a_.get(),
+ base::kNullProcessHandle, session_200);
+ Mock::VerifyAndClearExpectations(client_a_.get());
+
+ // 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());
+
+ // 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());
+ 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);
+ Mock::VerifyAndClearExpectations(client_b_.get());
+
+ // Third, fourth, and fifth frames. 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());
+
+ }
+ // ReserveOutputBuffer ought to fail now, because the pool is depleted.
+ ASSERT_FALSE(device_->ReserveOutputBuffer());
+ EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1)).Times(kPoolSize);
+ EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2)).Times(kPoolSize);
+ 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.
+ // 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();
+ {
+ // Kill A2 via session close (posts a task to disconnect, but A2 must not
+ // be sent either of these two frames)..
+ 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());
+ // B2 is the only client left, and is the only one that should
+ // get the frame.
+ EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_2)).Times(2);
+ base::RunLoop().RunUntilIdle();
+ Mock::VerifyAndClearExpectations(client_a_.get());
+ Mock::VerifyAndClearExpectations(client_b_.get());
+}
+
+// Exercises the OnError() codepath of VideoCaptureController, and tests the
+// 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;
+
+ 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);
+ device_->OnError();
+ EXPECT_CALL(*client_a_, DoError(route_id)).Times(1);
+ base::RunLoop().RunUntilIdle();
+ Mock::VerifyAndClearExpectations(client_a_.get());
+
+ // 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);
+ 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);
+
+ device_->OnFrameInfo(device_format);
+ base::RunLoop().RunUntilIdle();
}
-// Try to stop session before stopping capture.
-TEST_F(VideoCaptureControllerTest, StopSession) {
- media::VideoCaptureParams capture_params;
- capture_params.session_id = vcm_->video_session_id_;
- capture_params.width = 320;
- capture_params.height = 240;
- capture_params.frame_per_second = 30;
-
- InSequence s;
- EXPECT_CALL(*vcm_.get(),
- StartCapture(capture_params.width,
- capture_params.height,
- controller_.get())).Times(1);
- EXPECT_CALL(*controller_handler_,
- DoFrameInfo(controller_handler_->controller_id_))
- .Times(AtLeast(1));
- EXPECT_CALL(*controller_handler_,
- DoBufferCreated(controller_handler_->controller_id_))
- .Times(AtLeast(1));
- EXPECT_CALL(*controller_handler_,
- DoBufferReady(controller_handler_->controller_id_))
- .Times(AtLeast(1))
- .WillOnce(StopSession(controller_.get(),
- vcm_->video_session_id_,
- message_loop_.get()));
- EXPECT_CALL(*controller_handler_,
- DoEnded(controller_handler_->controller_id_))
- .Times(1);
-
- controller_->StartCapture(controller_handler_->controller_id_,
- controller_handler_.get(),
- controller_handler_->process_handle_,
- capture_params);
- message_loop_->Run();
-
- // The session is stopped now. There should be no buffer coming from
- // controller.
- EXPECT_CALL(*controller_handler_,
- DoBufferReady(controller_handler_->controller_id_))
- .Times(0);
- message_loop_->PostDelayedTask(FROM_HERE,
- base::MessageLoop::QuitClosure(), base::TimeDelta::FromSeconds(1));
- message_loop_->Run();
-
- EXPECT_CALL(*vcm_.get(), StopCapture(vcm_->video_session_id_)).Times(1);
- controller_->StopCapture(controller_handler_->controller_id_,
- controller_handler_.get());
+// Exercises the OnError() codepath of VideoCaptureController, and tests the
+// 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;
+
+ 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);
+ base::RunLoop().RunUntilIdle();
+ Mock::VerifyAndClearExpectations(client_a_.get());
+
+ scoped_refptr<media::VideoFrame> frame = device_->ReserveOutputBuffer();
+ ASSERT_TRUE(frame);
+
+ device_->OnError();
+ device_->OnIncomingCapturedVideoFrame(frame, base::Time());
+ frame = NULL;
+
+ EXPECT_CALL(*client_a_, DoError(route_id)).Times(1);
+ base::RunLoop().RunUntilIdle();
+ Mock::VerifyAndClearExpectations(client_a_.get());
+
+ // 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);
+ Mock::VerifyAndClearExpectations(client_b_.get());
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/video_capture_host.cc b/chromium/content/browser/renderer_host/media/video_capture_host.cc
index bc7c8c19d7d..7ed77ae53d3 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_host.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_host.cc
@@ -6,7 +6,6 @@
#include "base/bind.h"
#include "base/memory/scoped_ptr.h"
-#include "base/stl_util.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
@@ -14,15 +13,6 @@
namespace content {
-struct VideoCaptureHost::Entry {
- Entry(VideoCaptureController* controller)
- : controller(controller) {}
-
- ~Entry() {}
-
- scoped_refptr<VideoCaptureController> controller;
-};
-
VideoCaptureHost::VideoCaptureHost(MediaStreamManager* media_stream_manager)
: media_stream_manager_(media_stream_manager) {
}
@@ -32,17 +22,15 @@ VideoCaptureHost::~VideoCaptureHost() {}
void VideoCaptureHost::OnChannelClosing() {
BrowserMessageFilter::OnChannelClosing();
- // Since the IPC channel is gone, close all requested VideCaptureDevices.
+ // Since the IPC channel is gone, close all requested VideoCaptureDevices.
for (EntryMap::iterator it = entries_.begin(); it != entries_.end(); it++) {
- VideoCaptureController* controller = it->second->controller.get();
+ const base::WeakPtr<VideoCaptureController>& controller = it->second;
if (controller) {
VideoCaptureControllerID controller_id(it->first);
- controller->StopCapture(controller_id, this);
- media_stream_manager_->video_capture_manager()->RemoveController(
- controller, this);
+ media_stream_manager_->video_capture_manager()->StopCaptureForClient(
+ controller.get(), controller_id, this);
}
}
- STLDeleteValues(&entries_);
}
void VideoCaptureHost::OnDestruct() const {
@@ -95,11 +83,11 @@ void VideoCaptureHost::OnFrameInfoChanged(
const VideoCaptureControllerID& controller_id,
int width,
int height,
- int frame_per_second) {
+ int frame_rate) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&VideoCaptureHost::DoSendFrameInfoChangedOnIOThread,
- this, controller_id, width, height, frame_per_second));
+ this, controller_id, width, height, frame_rate));
}
void VideoCaptureHost::OnEnded(const VideoCaptureControllerID& controller_id) {
@@ -170,7 +158,7 @@ void VideoCaptureHost::DoSendFrameInfoOnIOThread(
media::VideoCaptureParams params;
params.width = format.width;
params.height = format.height;
- params.frame_per_second = format.frame_rate;
+ 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,
@@ -181,7 +169,7 @@ void VideoCaptureHost::DoSendFrameInfoChangedOnIOThread(
const VideoCaptureControllerID& controller_id,
int width,
int height,
- int frame_per_second) {
+ int frame_rate) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (entries_.find(controller_id) == entries_.end())
@@ -190,7 +178,7 @@ void VideoCaptureHost::DoSendFrameInfoChangedOnIOThread(
media::VideoCaptureParams params;
params.width = width;
params.height = height;
- params.frame_per_second = frame_per_second;
+ params.frame_rate = frame_rate;
Send(new VideoCaptureMsg_DeviceInfoChanged(controller_id.device_id, params));
}
@@ -215,7 +203,7 @@ void VideoCaptureHost::OnStartCapture(int device_id,
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DVLOG(1) << "VideoCaptureHost::OnStartCapture, device_id " << device_id
<< ", (" << params.width << ", " << params.height << ", "
- << params.frame_per_second << ", " << params.session_id
+ << params.frame_rate << ", " << params.session_id
<< ", variable resolution device:"
<< ((params.frame_size_type ==
media::VariableResolutionVideoCaptureDevice) ? "yes" : "no")
@@ -223,45 +211,44 @@ void VideoCaptureHost::OnStartCapture(int device_id,
VideoCaptureControllerID controller_id(device_id);
DCHECK(entries_.find(controller_id) == entries_.end());
- entries_[controller_id] = new Entry(NULL);
- media_stream_manager_->video_capture_manager()->AddController(
- params, this, base::Bind(&VideoCaptureHost::OnControllerAdded, this,
- device_id, params));
+ 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));
}
void VideoCaptureHost::OnControllerAdded(
int device_id, const media::VideoCaptureParams& params,
- VideoCaptureController* controller) {
+ const base::WeakPtr<VideoCaptureController>& controller) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&VideoCaptureHost::DoControllerAddedOnIOThread,
- this, device_id, params, make_scoped_refptr(controller)));
+ this, device_id, params, controller));
}
void VideoCaptureHost::DoControllerAddedOnIOThread(
int device_id, const media::VideoCaptureParams params,
- VideoCaptureController* controller) {
+ const base::WeakPtr<VideoCaptureController>& controller) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
VideoCaptureControllerID controller_id(device_id);
EntryMap::iterator it = entries_.find(controller_id);
if (it == entries_.end()) {
if (controller) {
- media_stream_manager_->video_capture_manager()->RemoveController(
- controller, this);
+ media_stream_manager_->video_capture_manager()->StopCaptureForClient(
+ controller.get(), controller_id, this);
}
return;
}
- if (controller == NULL) {
+ if (!controller) {
Send(new VideoCaptureMsg_StateChanged(device_id,
VIDEO_CAPTURE_STATE_ERROR));
- delete it->second;
entries_.erase(controller_id);
return;
}
- it->second->controller = controller;
- controller->StartCapture(controller_id, this, PeerHandle(), params);
+ DCHECK(!it->second);
+ it->second = controller;
}
void VideoCaptureHost::OnStopCapture(int device_id) {
@@ -288,8 +275,8 @@ void VideoCaptureHost::OnReceiveEmptyBuffer(int device_id, int buffer_id) {
VideoCaptureControllerID controller_id(device_id);
EntryMap::iterator it = entries_.find(controller_id);
if (it != entries_.end()) {
- scoped_refptr<VideoCaptureController> controller = it->second->controller;
- if (controller.get())
+ const base::WeakPtr<VideoCaptureController>& controller = it->second;
+ if (controller)
controller->ReturnBuffer(controller_id, this, buffer_id);
}
}
@@ -302,14 +289,11 @@ void VideoCaptureHost::DeleteVideoCaptureControllerOnIOThread(
if (it == entries_.end())
return;
- VideoCaptureController* controller = it->second->controller.get();
- if (controller) {
- controller->StopCapture(controller_id, this);
- media_stream_manager_->video_capture_manager()->RemoveController(
- controller, this);
+ if (it->second) {
+ media_stream_manager_->video_capture_manager()->StopCaptureForClient(
+ it->second.get(), controller_id, this);
}
- delete it->second;
- entries_.erase(controller_id);
+ entries_.erase(it);
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/video_capture_host.h b/chromium/content/browser/renderer_host/media/video_capture_host.h
index 025b849de94..6ce395631eb 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_host.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_host.h
@@ -39,6 +39,7 @@
#include <map>
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner_helpers.h"
#include "content/browser/renderer_host/media/video_capture_controller.h"
#include "content/common/content_export.h"
@@ -46,7 +47,7 @@
#include "ipc/ipc_message.h"
namespace media {
-struct VideoCaptureCapability;
+class VideoCaptureCapability;
}
namespace content {
@@ -97,10 +98,10 @@ class CONTENT_EXPORT VideoCaptureHost
const media::VideoCaptureParams& params);
void OnControllerAdded(
int device_id, const media::VideoCaptureParams& params,
- VideoCaptureController* controller);
+ const base::WeakPtr<VideoCaptureController>& controller);
void DoControllerAddedOnIOThread(
int device_id, const media::VideoCaptureParams params,
- VideoCaptureController* controller);
+ const base::WeakPtr<VideoCaptureController>& controller);
// IPC message: Stop capture on device referenced by |device_id|.
void OnStopCapture(int device_id);
@@ -148,9 +149,12 @@ class CONTENT_EXPORT VideoCaptureHost
MediaStreamManager* media_stream_manager_;
- struct Entry;
- typedef std::map<VideoCaptureControllerID, Entry*> EntryMap;
- // A map of VideoCaptureControllerID to its state and VideoCaptureController.
+ typedef std::map<VideoCaptureControllerID,
+ base::WeakPtr<VideoCaptureController> > EntryMap;
+
+ // A map of VideoCaptureControllerID to the VideoCaptureController to which it
+ // is connected. An entry in this map holds a null controller while it is in
+ // the process of starting.
EntryMap entries_;
DISALLOW_COPY_AND_ASSIGN(VideoCaptureHost);
diff --git a/chromium/content/browser/renderer_host/media/video_capture_host_unittest.cc b/chromium/content/browser/renderer_host/media/video_capture_host_unittest.cc
index 762148c86a2..ca1891dc426 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
@@ -20,6 +20,7 @@
#include "content/public/test/mock_resource_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "media/audio/audio_manager.h"
+#include "media/base/video_frame.h"
#include "media/video/capture/video_capture_types.h"
#include "net/url_request/url_request_context.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -36,10 +37,10 @@ using ::testing::Return;
namespace content {
// Id used to identify the capture session between renderer and
-// video_capture_host.
-static const int kDeviceId = 1;
+// video_capture_host. This is an arbitrary value.
+static const int kDeviceId = 555;
// Id of a video capture device
-static const media::VideoCaptureSessionId kTestFakeDeviceId =
+static const media::VideoCaptureSessionId kTestFakeSessionId =
VideoCaptureManager::kStartOpenSessionId;
// Define to enable test where video is dumped to file.
@@ -57,7 +58,8 @@ class DumpVideo {
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"));
- expected_size_ = width * height * 3 / 2;
+ expected_size_ = media::VideoFrame::AllocationSize(
+ media::VideoFrame::I420, gfx::Size(width, height));
}
void NewVideoFrame(const void* buffer) {
if (file_.get() != NULL) {
@@ -146,7 +148,8 @@ class MockVideoCaptureHost : public VideoCaptureHost {
// These handler methods do minimal things and delegate to the mock methods.
void OnNewBufferCreatedDispatch(int device_id,
base::SharedMemoryHandle handle,
- int length, int buffer_id) {
+ uint32 length,
+ int buffer_id) {
OnNewBufferCreated(device_id, handle, length, buffer_id);
base::SharedMemory* dib = new base::SharedMemory(handle, false);
dib->Map(length);
@@ -249,14 +252,31 @@ class VideoCaptureHostTest : public testing::Test {
media::VideoCaptureParams params;
params.width = 352;
params.height = 288;
- params.frame_per_second = 30;
- params.session_id = kTestFakeDeviceId;
+ params.frame_rate = 30;
+ params.session_id = kTestFakeSessionId;
host_->OnStartCapture(kDeviceId, params);
run_loop.Run();
}
+ void StartStopCapture() {
+ // Quickly start and then stop capture, without giving much chance for
+ // asynchronous start operations to complete.
+ InSequence s;
+ base::RunLoop run_loop;
+ EXPECT_CALL(*host_.get(),
+ OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_STOPPED));
+ media::VideoCaptureParams params;
+ params.width = 352;
+ params.height = 288;
+ params.frame_rate = 30;
+ params.session_id = kTestFakeSessionId;
+ host_->OnStartCapture(kDeviceId, params);
+ host_->OnStopCapture(kDeviceId);
+ run_loop.RunUntilIdle();
+ }
+
#ifdef DUMP_VIDEO
- void CaptureAndDumpVideo(int width, int heigt, int frame_rate) {
+ void CaptureAndDumpVideo(int width, int height, int frame_rate) {
InSequence s;
// 1. First - get info about the new resolution
EXPECT_CALL(*host_, OnDeviceInfo(kDeviceId));
@@ -272,9 +292,9 @@ class VideoCaptureHostTest : public testing::Test {
media::VideoCaptureParams params;
params.width = width;
- params.height = heigt;
- params.frame_per_second = frame_rate;
- params.session_id = kTestFakeDeviceId;
+ params.height = height;
+ params.frame_rate = frame_rate;
+ params.session_id = kTestFakeSessionId;
host_->SetDumpVideo(true);
host_->OnStartCapture(kDeviceId, params);
run_loop.Run();
@@ -336,6 +356,12 @@ TEST_F(VideoCaptureHostTest, StartCapture) {
StartCapture();
}
+// 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) {
+ StartStopCapture();
+}
+
TEST_F(VideoCaptureHostTest, StartCapturePlayStop) {
StartCapture();
NotifyPacketReady();
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 79da41260a3..f61aa83d093 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_manager.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_manager.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
#include "base/stl_util.h"
#include "base/threading/sequenced_worker_pool.h"
#include "content/browser/renderer_host/media/video_capture_controller.h"
@@ -33,20 +34,15 @@ namespace content {
// explicitly calling open device.
enum { kFirstSessionId = VideoCaptureManager::kStartOpenSessionId + 1 };
-struct VideoCaptureManager::Controller {
- Controller(
- VideoCaptureController* vc_controller,
- VideoCaptureControllerEventHandler* handler)
- : controller(vc_controller),
- ready_to_delete(false) {
- handlers.push_front(handler);
- }
- ~Controller() {}
+VideoCaptureManager::DeviceEntry::DeviceEntry(
+ MediaStreamType stream_type,
+ const std::string& id,
+ scoped_ptr<VideoCaptureController> controller)
+ : stream_type(stream_type),
+ id(id),
+ video_capture_controller(controller.Pass()) {}
- scoped_refptr<VideoCaptureController> controller;
- bool ready_to_delete;
- Handlers handlers;
-};
+VideoCaptureManager::DeviceEntry::~DeviceEntry() {}
VideoCaptureManager::VideoCaptureManager()
: listener_(NULL),
@@ -56,7 +52,6 @@ VideoCaptureManager::VideoCaptureManager()
VideoCaptureManager::~VideoCaptureManager() {
DCHECK(devices_.empty());
- DCHECK(controllers_.empty());
}
void VideoCaptureManager::Register(MediaStreamProviderListener* listener,
@@ -75,109 +70,87 @@ void VideoCaptureManager::Unregister() {
void VideoCaptureManager::EnumerateDevices(MediaStreamType stream_type) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DVLOG(1) << "VideoCaptureManager::EnumerateDevices, type " << stream_type;
DCHECK(listener_);
- device_loop_->PostTask(
- FROM_HERE,
- base::Bind(&VideoCaptureManager::OnEnumerateDevices, this, stream_type));
+ base::PostTaskAndReplyWithResult(
+ device_loop_, FROM_HERE,
+ base::Bind(&VideoCaptureManager::GetAvailableDevicesOnDeviceThread, this,
+ stream_type),
+ base::Bind(&VideoCaptureManager::OnDevicesEnumerated, this, stream_type));
}
-int VideoCaptureManager::Open(const StreamDeviceInfo& device) {
+int VideoCaptureManager::Open(const StreamDeviceInfo& device_info) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(listener_);
- // Generate a new id for this device.
- int video_capture_session_id = new_capture_session_id_++;
+ // Generate a new id for the session being opened.
+ const int capture_session_id = new_capture_session_id_++;
- device_loop_->PostTask(
- FROM_HERE,
- base::Bind(&VideoCaptureManager::OnOpen, this, video_capture_session_id,
- device));
+ DCHECK(sessions_.find(capture_session_id) == sessions_.end());
+ DVLOG(1) << "VideoCaptureManager::Open, id " << capture_session_id;
- return video_capture_session_id;
+ // We just save the stream info for processing later.
+ sessions_[capture_session_id] = device_info.device;
+
+ // Notify our listener asynchronously; this ensures that we return
+ // |capture_session_id| to the caller of this function before using that same
+ // id in a listener event.
+ base::MessageLoop::current()->PostTask(FROM_HERE,
+ base::Bind(&VideoCaptureManager::OnOpened, this,
+ device_info.device.type, capture_session_id));
+ return capture_session_id;
}
void VideoCaptureManager::Close(int capture_session_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(listener_);
DVLOG(1) << "VideoCaptureManager::Close, id " << capture_session_id;
- device_loop_->PostTask(
- FROM_HERE,
- base::Bind(&VideoCaptureManager::OnClose, this, capture_session_id));
-}
-void VideoCaptureManager::Start(
- const media::VideoCaptureParams& capture_params,
- media::VideoCaptureDevice::EventHandler* video_capture_receiver) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- device_loop_->PostTask(
- FROM_HERE,
- base::Bind(&VideoCaptureManager::OnStart, this, capture_params,
- video_capture_receiver));
-}
+ std::map<int, MediaStreamDevice>::iterator session_it =
+ sessions_.find(capture_session_id);
+ if (session_it == sessions_.end()) {
+ NOTREACHED();
+ return;
+ }
-void VideoCaptureManager::Stop(
- const media::VideoCaptureSessionId& capture_session_id,
- base::Closure stopped_cb) {
- DVLOG(1) << "VideoCaptureManager::Stop, id " << capture_session_id;
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- device_loop_->PostTask(
- FROM_HERE,
- base::Bind(&VideoCaptureManager::OnStop, this, capture_session_id,
- stopped_cb));
+ DeviceEntry* const existing_device = GetDeviceEntryForMediaStreamDevice(
+ session_it->second);
+ if (existing_device) {
+ // Remove any client that is still using the session. This is safe to call
+ // even if there are no clients using the session.
+ existing_device->video_capture_controller->StopSession(capture_session_id);
+
+ // StopSession() may have removed the last client, so we might need to
+ // close the device.
+ DestroyDeviceEntryIfNoClients(existing_device);
+ }
+
+ // Notify listeners asynchronously, and forget the session.
+ base::MessageLoop::current()->PostTask(FROM_HERE,
+ base::Bind(&VideoCaptureManager::OnClosed, this, session_it->second.type,
+ capture_session_id));
+ sessions_.erase(session_it);
}
void VideoCaptureManager::UseFakeDevice() {
use_fake_device_ = true;
}
-void VideoCaptureManager::OnEnumerateDevices(MediaStreamType stream_type) {
- SCOPED_UMA_HISTOGRAM_TIMER(
- "Media.VideoCaptureManager.OnEnumerateDevicesTime");
- DCHECK(IsOnDeviceThread());
-
- media::VideoCaptureDevice::Names device_names;
- GetAvailableDevices(stream_type, &device_names);
-
- scoped_ptr<StreamDeviceInfoArray> devices(new StreamDeviceInfoArray());
- for (media::VideoCaptureDevice::Names::iterator it =
- device_names.begin(); it != device_names.end(); ++it) {
- bool opened = DeviceOpened(*it);
- devices->push_back(StreamDeviceInfo(
- stream_type, it->GetNameAndModel(), it->id(), opened));
- }
-
- PostOnDevicesEnumerated(stream_type, devices.Pass());
-}
-
-void VideoCaptureManager::OnOpen(int capture_session_id,
- const StreamDeviceInfo& device) {
- SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.OnOpenTime");
+void VideoCaptureManager::DoStartDeviceOnDeviceThread(
+ DeviceEntry* entry,
+ const media::VideoCaptureCapability& capture_params,
+ scoped_ptr<media::VideoCaptureDevice::EventHandler> device_client) {
+ SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime");
DCHECK(IsOnDeviceThread());
- DCHECK(devices_.find(capture_session_id) == devices_.end());
- DVLOG(1) << "VideoCaptureManager::OnOpen, id " << capture_session_id;
-
- // Check if another session has already opened this device. If so, just
- // use that opened device.
- media::VideoCaptureDevice* opened_video_capture_device =
- GetOpenedDevice(device);
- if (opened_video_capture_device) {
- DeviceEntry& new_entry = devices_[capture_session_id];
- new_entry.stream_type = device.device.type;
- new_entry.capture_device = opened_video_capture_device;
- PostOnOpened(device.device.type, capture_session_id);
- return;
- }
scoped_ptr<media::VideoCaptureDevice> video_capture_device;
-
- // Open the device.
- switch (device.device.type) {
+ switch (entry->stream_type) {
case MEDIA_DEVICE_VIDEO_CAPTURE: {
// 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(device.device.id);
+ video_capture_devices_.FindById(entry->id);
if (found) {
video_capture_device.reset(use_fake_device_ ?
media::FakeVideoCaptureDevice::Create(*found) :
@@ -187,12 +160,12 @@ void VideoCaptureManager::OnOpen(int capture_session_id,
}
case MEDIA_TAB_VIDEO_CAPTURE: {
video_capture_device.reset(
- WebContentsVideoCaptureDevice::Create(device.device.id));
+ WebContentsVideoCaptureDevice::Create(entry->id));
break;
}
case MEDIA_DESKTOP_VIDEO_CAPTURE: {
#if defined(ENABLE_SCREEN_CAPTURE)
- DesktopMediaID id = DesktopMediaID::Parse(device.device.id);
+ DesktopMediaID id = DesktopMediaID::Parse(entry->id);
if (id.type != DesktopMediaID::TYPE_NONE) {
video_capture_device = DesktopCaptureDevice::Create(id);
}
@@ -206,128 +179,123 @@ void VideoCaptureManager::OnOpen(int capture_session_id,
}
if (!video_capture_device) {
- PostOnError(capture_session_id, kDeviceNotAvailable);
+ device_client->OnError();
return;
}
- DeviceEntry& new_entry = devices_[capture_session_id];
- new_entry.stream_type = device.device.type;
- new_entry.capture_device = video_capture_device.release();
- PostOnOpened(device.device.type, capture_session_id);
+ video_capture_device->AllocateAndStart(capture_params, device_client.Pass());
+ entry->video_capture_device = video_capture_device.Pass();
}
-void VideoCaptureManager::OnClose(int capture_session_id) {
- SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.OnCloseTime");
- DCHECK(IsOnDeviceThread());
- DVLOG(1) << "VideoCaptureManager::OnClose, id " << capture_session_id;
-
- VideoCaptureDevices::iterator device_it = devices_.find(capture_session_id);
- if (device_it == devices_.end()) {
+void VideoCaptureManager::StartCaptureForClient(
+ 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));
+ 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);
}
- const DeviceEntry removed_entry = device_it->second;
- devices_.erase(device_it);
-
- Controllers::iterator cit = controllers_.find(removed_entry.capture_device);
- if (cit != controllers_.end()) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&VideoCaptureController::StopSession,
- cit->second->controller, capture_session_id));
- }
+}
- if (!DeviceInUse(removed_entry.capture_device)) {
- // No other users of this device, deallocate (if not done already) and
- // delete the device. No need to take care of the controller, that is done
- // by |OnStop|.
- removed_entry.capture_device->DeAllocate();
- Controllers::iterator cit = controllers_.find(removed_entry.capture_device);
- if (cit != controllers_.end()) {
- delete cit->second;
- controllers_.erase(cit);
- }
- delete removed_entry.capture_device;
+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);
+ if (!entry) {
+ done_cb.Run(base::WeakPtr<VideoCaptureController>());
+ return;
}
- PostOnClosed(removed_entry.stream_type, capture_session_id);
-}
+ DCHECK(entry->video_capture_controller);
-void VideoCaptureManager::OnStart(
- const media::VideoCaptureParams capture_params,
- media::VideoCaptureDevice::EventHandler* video_capture_receiver) {
- SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.OnStartTime");
- DCHECK(IsOnDeviceThread());
- DCHECK(video_capture_receiver != NULL);
- DVLOG(1) << "VideoCaptureManager::OnStart, (" << capture_params.width
- << ", " << capture_params.height
- << ", " << capture_params.frame_per_second
- << ", " << capture_params.session_id
- << ")";
-
- media::VideoCaptureDevice* video_capture_device =
- GetDeviceInternal(capture_params.session_id);
- if (!video_capture_device) {
- // Invalid session id.
- video_capture_receiver->OnError();
- return;
+ // First client starts the device.
+ if (entry->video_capture_controller->GetClientCount() == 0) {
+ 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())));
}
- // TODO(mcasas): Variable resolution video capture devices, are not yet
- // fully supported, see crbug.com/261410, second part, and crbug.com/266082 .
- if (capture_params.frame_size_type !=
- media::ConstantResolutionVideoCaptureDevice) {
- LOG(DFATAL) << "Only constant Video Capture resolution device supported.";
- video_capture_receiver->OnError();
+ // 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);
+}
+
+void VideoCaptureManager::StopCaptureForClient(
+ VideoCaptureController* controller,
+ VideoCaptureControllerID client_id,
+ VideoCaptureControllerEventHandler* client_handler) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(controller);
+ DCHECK(client_handler);
+
+ DeviceEntry* entry = GetDeviceEntryForController(controller);
+ if (!entry) {
+ NOTREACHED();
return;
}
- Controllers::iterator cit = controllers_.find(video_capture_device);
- if (cit != controllers_.end()) {
- cit->second->ready_to_delete = false;
- }
- // Possible errors are signaled to video_capture_receiver by
- // video_capture_device. video_capture_receiver to perform actions.
- media::VideoCaptureCapability params_as_capability_copy;
- params_as_capability_copy.width = capture_params.width;
- params_as_capability_copy.height = capture_params.height;
- params_as_capability_copy.frame_rate = capture_params.frame_per_second;
- params_as_capability_copy.session_id = capture_params.session_id;
- params_as_capability_copy.frame_size_type = capture_params.frame_size_type;
- video_capture_device->Allocate(params_as_capability_copy,
- video_capture_receiver);
- video_capture_device->Start();
-}
+ // Detach client from controller.
+ int session_id = controller->RemoveClient(client_id, client_handler);
+ DVLOG(1) << "VideoCaptureManager::StopCaptureForClient, session_id = "
+ << session_id;
-void VideoCaptureManager::OnStop(
- const media::VideoCaptureSessionId capture_session_id,
- base::Closure stopped_cb) {
- SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.OnStopTime");
- DCHECK(IsOnDeviceThread());
- DVLOG(1) << "VideoCaptureManager::OnStop, id " << capture_session_id;
-
- VideoCaptureDevices::iterator it = devices_.find(capture_session_id);
- if (it != devices_.end()) {
- media::VideoCaptureDevice* video_capture_device = it->second.capture_device;
- // Possible errors are signaled to video_capture_receiver by
- // video_capture_device. video_capture_receiver to perform actions.
- video_capture_device->Stop();
- video_capture_device->DeAllocate();
- Controllers::iterator cit = controllers_.find(video_capture_device);
- if (cit != controllers_.end()) {
- cit->second->ready_to_delete = true;
- if (cit->second->handlers.empty()) {
- delete cit->second;
- controllers_.erase(cit);
- }
- }
- }
+ // If controller has no more clients, delete controller and device.
+ DestroyDeviceEntryIfNoClients(entry);
- if (!stopped_cb.is_null())
- stopped_cb.Run();
+ // 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));
+ }
+}
- if (capture_session_id == kStartOpenSessionId) {
- // This device was opened from Start(), not Open(). Close it!
- OnClose(capture_session_id);
+void VideoCaptureManager::DoStopDeviceOnDeviceThread(DeviceEntry* entry) {
+ SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StopDeviceTime");
+ DCHECK(IsOnDeviceThread());
+ if (entry->video_capture_device) {
+ entry->video_capture_device->StopAndDeAllocate();
}
+ entry->video_capture_device.reset();
}
void VideoCaptureManager::OnOpened(MediaStreamType stream_type,
@@ -352,242 +320,173 @@ void VideoCaptureManager::OnClosed(MediaStreamType stream_type,
void VideoCaptureManager::OnDevicesEnumerated(
MediaStreamType stream_type,
- scoped_ptr<StreamDeviceInfoArray> devices) {
+ const media::VideoCaptureDevice::Names& device_names) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- if (!listener_) {
- // Listener has been removed.
- return;
- }
- listener_->DevicesEnumerated(stream_type, *devices);
-}
-void VideoCaptureManager::OnError(MediaStreamType stream_type,
- int capture_session_id,
- MediaStreamProviderError error) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (!listener_) {
// Listener has been removed.
return;
}
- listener_->Error(stream_type, capture_session_id, error);
-}
-void VideoCaptureManager::PostOnOpened(
- MediaStreamType stream_type, int capture_session_id) {
- DCHECK(IsOnDeviceThread());
- BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(&VideoCaptureManager::OnOpened, this,
- stream_type, capture_session_id));
-}
-
-void VideoCaptureManager::PostOnClosed(
- MediaStreamType stream_type, int capture_session_id) {
- DCHECK(IsOnDeviceThread());
- BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(&VideoCaptureManager::OnClosed, this,
- stream_type, capture_session_id));
-}
-
-void VideoCaptureManager::PostOnDevicesEnumerated(
- MediaStreamType stream_type,
- scoped_ptr<StreamDeviceInfoArray> devices) {
- DCHECK(IsOnDeviceThread());
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&VideoCaptureManager::OnDevicesEnumerated,
- this, stream_type, base::Passed(&devices)));
-}
+ // Transform from VCD::Name to StreamDeviceInfo.
+ StreamDeviceInfoArray devices;
+ for (media::VideoCaptureDevice::Names::const_iterator it =
+ device_names.begin(); it != device_names.end(); ++it) {
+ devices.push_back(StreamDeviceInfo(
+ stream_type, it->GetNameAndModel(), it->id(), false));
+ }
-void VideoCaptureManager::PostOnError(int capture_session_id,
- MediaStreamProviderError error) {
- DCHECK(IsOnDeviceThread());
- MediaStreamType stream_type = MEDIA_DEVICE_VIDEO_CAPTURE;
- VideoCaptureDevices::const_iterator it = devices_.find(capture_session_id);
- if (it != devices_.end())
- stream_type = it->second.stream_type;
- BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(&VideoCaptureManager::OnError, this,
- stream_type, capture_session_id, error));
+ listener_->DevicesEnumerated(stream_type, devices);
}
bool VideoCaptureManager::IsOnDeviceThread() const {
return device_loop_->BelongsToCurrentThread();
}
-void VideoCaptureManager::GetAvailableDevices(
- MediaStreamType stream_type,
- media::VideoCaptureDevice::Names* device_names) {
+media::VideoCaptureDevice::Names
+VideoCaptureManager::GetAvailableDevicesOnDeviceThread(
+ MediaStreamType stream_type) {
+ SCOPED_UMA_HISTOGRAM_TIMER(
+ "Media.VideoCaptureManager.GetAvailableDevicesTime");
DCHECK(IsOnDeviceThread());
+ media::VideoCaptureDevice::Names result;
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.
- video_capture_devices_.clear();
if (!use_fake_device_) {
- media::VideoCaptureDevice::GetDeviceNames(&video_capture_devices_);
+ media::VideoCaptureDevice::GetDeviceNames(&result);
} else {
- media::FakeVideoCaptureDevice::GetDeviceNames(&video_capture_devices_);
+ media::FakeVideoCaptureDevice::GetDeviceNames(&result);
}
- *device_names = video_capture_devices_;
+
+ // 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:
- device_names->clear();
+ // Do nothing.
break;
default:
NOTREACHED();
break;
}
+ return result;
}
-bool VideoCaptureManager::DeviceOpened(
- const media::VideoCaptureDevice::Name& device_name) {
- DCHECK(IsOnDeviceThread());
+VideoCaptureManager::DeviceEntry*
+VideoCaptureManager::GetDeviceEntryForMediaStreamDevice(
+ const MediaStreamDevice& device_info) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- for (VideoCaptureDevices::iterator it = devices_.begin();
+ for (DeviceEntries::iterator it = devices_.begin();
it != devices_.end(); ++it) {
- if (device_name.id() == it->second.capture_device->device_name().id()) {
- // We've found the device!
- return true;
- }
- }
- return false;
-}
-
-media::VideoCaptureDevice* VideoCaptureManager::GetOpenedDevice(
- const StreamDeviceInfo& device_info) {
- DCHECK(IsOnDeviceThread());
-
- for (VideoCaptureDevices::iterator it = devices_.begin();
- it != devices_.end(); it++) {
- if (device_info.device.id ==
- it->second.capture_device->device_name().id()) {
- return it->second.capture_device;
+ DeviceEntry* device = *it;
+ if (device_info.type == device->stream_type &&
+ device_info.id == device->id) {
+ return device;
}
}
return NULL;
}
-bool VideoCaptureManager::DeviceInUse(
- const media::VideoCaptureDevice* video_capture_device) {
- DCHECK(IsOnDeviceThread());
-
- for (VideoCaptureDevices::iterator it = devices_.begin();
+VideoCaptureManager::DeviceEntry*
+VideoCaptureManager::GetDeviceEntryForController(
+ const VideoCaptureController* controller) {
+ // Look up |controller| in |devices_|.
+ for (DeviceEntries::iterator it = devices_.begin();
it != devices_.end(); ++it) {
- if (video_capture_device == it->second.capture_device) {
- // We've found the device!
- return true;
+ if ((*it)->video_capture_controller.get() == controller) {
+ return *it;
}
}
- return false;
+ return NULL;
}
-void VideoCaptureManager::AddController(
+void VideoCaptureManager::OpenAndStartDefaultSession(
const media::VideoCaptureParams& capture_params,
- VideoCaptureControllerEventHandler* handler,
- base::Callback<void(VideoCaptureController*)> added_cb) {
- DCHECK(handler);
- device_loop_->PostTask(
- FROM_HERE,
- base::Bind(&VideoCaptureManager::DoAddControllerOnDeviceThread,
- this, capture_params, handler, added_cb));
-}
-
-void VideoCaptureManager::DoAddControllerOnDeviceThread(
- const media::VideoCaptureParams capture_params,
- VideoCaptureControllerEventHandler* handler,
- base::Callback<void(VideoCaptureController*)> added_cb) {
- DCHECK(IsOnDeviceThread());
+ 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));
- media::VideoCaptureDevice* video_capture_device =
- GetDeviceInternal(capture_params.session_id);
- scoped_refptr<VideoCaptureController> controller;
- if (video_capture_device) {
- Controllers::iterator cit = controllers_.find(video_capture_device);
- if (cit == controllers_.end()) {
- controller = new VideoCaptureController(this);
- controllers_[video_capture_device] =
- new Controller(controller.get(), handler);
- } else {
- controllers_[video_capture_device]->handlers.push_front(handler);
- controller = controllers_[video_capture_device]->controller;
- }
+ // |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;
}
- added_cb.Run(controller.get());
-}
-void VideoCaptureManager::RemoveController(
- VideoCaptureController* controller,
- VideoCaptureControllerEventHandler* handler) {
- DCHECK(handler);
- device_loop_->PostTask(
- FROM_HERE,
- base::Bind(&VideoCaptureManager::DoRemoveControllerOnDeviceThread, this,
- make_scoped_refptr(controller), handler));
-}
+ // 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());
-void VideoCaptureManager::DoRemoveControllerOnDeviceThread(
- VideoCaptureController* controller,
- VideoCaptureControllerEventHandler* handler) {
- DCHECK(IsOnDeviceThread());
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&VideoCaptureManager::OnOpened, this,
+ MEDIA_DEVICE_VIDEO_CAPTURE, kStartOpenSessionId));
- for (Controllers::iterator cit = controllers_.begin();
- cit != controllers_.end(); ++cit) {
- if (controller == cit->second->controller.get()) {
- Handlers& handlers = cit->second->handlers;
- for (Handlers::iterator hit = handlers.begin();
- hit != handlers.end(); ++hit) {
- if ((*hit) == handler) {
- handlers.erase(hit);
- break;
- }
- }
- if (handlers.empty() && cit->second->ready_to_delete) {
- delete cit->second;
- controllers_.erase(cit);
- }
- return;
- }
- }
+ DoStartCaptureForClient(capture_params, client_render_process, client_id,
+ client_handler, done_cb);
}
-media::VideoCaptureDevice* VideoCaptureManager::GetDeviceInternal(
- int capture_session_id) {
- DCHECK(IsOnDeviceThread());
- VideoCaptureDevices::iterator dit = devices_.find(capture_session_id);
- if (dit != devices_.end()) {
- return dit->second.capture_device;
+void VideoCaptureManager::DestroyDeviceEntryIfNoClients(DeviceEntry* entry) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ // Removal of the last client stops the device.
+ if (entry->video_capture_controller->GetClientCount() == 0) {
+ DVLOG(1) << "VideoCaptureManager stopping device (type = "
+ << entry->stream_type << ", id = " << entry->id << ")";
+
+ // The DeviceEntry is removed from |devices_| immediately. The controller is
+ // deleted immediately, and the device is freed asynchronously. After this
+ // point, subsequent requests to open this same device ID will create a new
+ // DeviceEntry, VideoCaptureController, and VideoCaptureDevice.
+ devices_.erase(entry);
+ entry->video_capture_controller.reset();
+ device_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this,
+ base::Owned(entry)));
}
+}
- // Solution for not using MediaStreamManager.
- // This session id won't be returned by Open().
- if (capture_session_id == kStartOpenSessionId) {
- media::VideoCaptureDevice::Names device_names;
- GetAvailableDevices(MEDIA_DEVICE_VIDEO_CAPTURE, &device_names);
- if (device_names.empty()) {
- // No devices available.
- return NULL;
- }
- StreamDeviceInfo device(MEDIA_DEVICE_VIDEO_CAPTURE,
- device_names.front().GetNameAndModel(),
- device_names.front().id(),
- false);
+VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry(
+ int capture_session_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- // Call OnOpen to open using the first device in the list.
- OnOpen(capture_session_id, device);
+ std::map<int, MediaStreamDevice>::iterator session_it =
+ sessions_.find(capture_session_id);
+ if (session_it == sessions_.end()) {
+ return NULL;
+ }
+ const MediaStreamDevice& device_info = session_it->second;
- VideoCaptureDevices::iterator dit = devices_.find(capture_session_id);
- if (dit != devices_.end()) {
- return dit->second.capture_device;
- }
+ // Check if another session has already opened this device. If so, just
+ // use that opened device.
+ DeviceEntry* const existing_device =
+ GetDeviceEntryForMediaStreamDevice(device_info);
+ if (existing_device) {
+ DCHECK_EQ(device_info.type, existing_device->stream_type);
+ return existing_device;
}
- return NULL;
+
+ scoped_ptr<VideoCaptureController> video_capture_controller(
+ new VideoCaptureController());
+ DeviceEntry* new_device = new DeviceEntry(device_info.type,
+ device_info.id,
+ video_capture_controller.Pass());
+ devices_.insert(new_device);
+ return new_device;
}
} // 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 34d6e626413..fc6dd92fecd 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_manager.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_manager.h
@@ -4,31 +4,39 @@
// VideoCaptureManager is used to open/close, start/stop, enumerate available
// video capture devices, and manage VideoCaptureController's.
-// All functions are expected to be called from Browser::IO thread.
+// All functions are expected to be called from Browser::IO thread. Some helper
+// functions (*OnDeviceThread) will dispatch operations to the device thread.
// VideoCaptureManager will open OS dependent instances of VideoCaptureDevice.
// A device can only be opened once.
#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_MANAGER_H_
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_MANAGER_H_
-#include <list>
#include <map>
+#include <set>
+#include <string>
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/process/process_handle.h"
#include "content/browser/renderer_host/media/media_stream_provider.h"
+#include "content/browser/renderer_host/media/video_capture_controller_event_handler.h"
#include "content/common/content_export.h"
#include "content/common/media/media_stream_options.h"
#include "media/video/capture/video_capture_device.h"
#include "media/video/capture/video_capture_types.h"
namespace content {
-class MockVideoCaptureManager;
class VideoCaptureController;
class VideoCaptureControllerEventHandler;
// VideoCaptureManager opens/closes and start/stops video capture devices.
class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
public:
+ // Callback used to signal the completion of a controller lookup.
+ 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.
@@ -48,118 +56,147 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
virtual void Close(int capture_session_id) OVERRIDE;
- // Functions used to start and stop media flow.
- // Start allocates the device and no other application can use the device
- // before Stop is called. Captured video frames will be delivered to
- // video_capture_receiver.
- virtual void Start(const media::VideoCaptureParams& capture_params,
- media::VideoCaptureDevice::EventHandler* video_capture_receiver);
-
- // Stops capture device referenced by |capture_session_id|. No more frames
- // will be delivered to the frame receiver, and |stopped_cb| will be called.
- // |stopped_cb| can be NULL.
- virtual void Stop(const media::VideoCaptureSessionId& capture_session_id,
- base::Closure stopped_cb);
-
// Used by unit test to make sure a fake device is used instead of a real
// video capture device. Due to timing requirements, the function must be
// called before EnumerateDevices and Open.
void UseFakeDevice();
- // Called by VideoCaptureHost to get a controller for |capture_params|.
- // The controller is returned via calling |added_cb|.
- void AddController(
- const media::VideoCaptureParams& capture_params,
- VideoCaptureControllerEventHandler* handler,
- base::Callback<void(VideoCaptureController*)> added_cb);
- // Called by VideoCaptureHost to remove the |controller|.
- void RemoveController(
- VideoCaptureController* controller,
- VideoCaptureControllerEventHandler* handler);
+ // 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;
+ // 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
+ // capturing from this device), this call will cause a VideoCaptureController
+ // and VideoCaptureDevice to be created, possibly asynchronously.
+ //
+ // 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,
+ base::ProcessHandle client_render_process,
+ VideoCaptureControllerID client_id,
+ VideoCaptureControllerEventHandler* client_handler,
+ const DoneCB& done_cb);
+
+ // Called by VideoCaptureHost to remove |client_handler|. If this is the last
+ // client of the device, the |controller| and its VideoCaptureDevice may be
+ // destroyed. The client must not access |controller| after calling this
+ // function.
+ void StopCaptureForClient(VideoCaptureController* controller,
+ VideoCaptureControllerID client_id,
+ VideoCaptureControllerEventHandler* client_handler);
private:
- friend class MockVideoCaptureManager;
-
virtual ~VideoCaptureManager();
+ struct DeviceEntry;
- typedef std::list<VideoCaptureControllerEventHandler*> Handlers;
- struct Controller;
-
- // Called by the public functions, executed on device thread.
- void OnEnumerateDevices(MediaStreamType stream_type);
- void OnOpen(int capture_session_id, const StreamDeviceInfo& device);
- void OnClose(int capture_session_id);
- void OnStart(const media::VideoCaptureParams capture_params,
- media::VideoCaptureDevice::EventHandler* video_capture_receiver);
- void OnStop(const media::VideoCaptureSessionId capture_session_id,
- base::Closure stopped_cb);
- void DoAddControllerOnDeviceThread(
- const media::VideoCaptureParams capture_params,
- VideoCaptureControllerEventHandler* handler,
- base::Callback<void(VideoCaptureController*)> added_cb);
- void DoRemoveControllerOnDeviceThread(
- VideoCaptureController* controller,
- VideoCaptureControllerEventHandler* handler);
-
- // Executed on Browser::IO thread to call Listener.
+ // 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);
+
+ // 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|
+ // may be freed by this function.
+ void DestroyDeviceEntryIfNoClients(DeviceEntry* entry);
+
+ // 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,
- scoped_ptr<StreamDeviceInfoArray> devices);
- void OnError(MediaStreamType type, int capture_session_id,
- MediaStreamProviderError error);
-
- // Executed on device thread to make sure Listener is called from
- // Browser::IO thread.
- void PostOnOpened(MediaStreamType type, int capture_session_id);
- void PostOnClosed(MediaStreamType type, int capture_session_id);
- void PostOnDevicesEnumerated(MediaStreamType stream_type,
- scoped_ptr<StreamDeviceInfoArray> devices);
- void PostOnError(int capture_session_id, MediaStreamProviderError error);
-
- // Helpers
- void GetAvailableDevices(MediaStreamType stream_type,
- media::VideoCaptureDevice::Names* device_names);
- bool DeviceOpened(const media::VideoCaptureDevice::Name& device_name);
- bool DeviceInUse(const media::VideoCaptureDevice* video_capture_device);
- media::VideoCaptureDevice* GetOpenedDevice(
- const StreamDeviceInfo& device_info);
+ const media::VideoCaptureDevice::Names& names);
+
+ // Find a DeviceEntry by its device ID and type, if it is already opened.
+ DeviceEntry* GetDeviceEntryForMediaStreamDevice(
+ const MediaStreamDevice& device_info);
+
+ // Find a DeviceEntry entry for the indicated session, creating a fresh one
+ // if necessary. Returns NULL if the session id is invalid.
+ DeviceEntry* GetOrCreateDeviceEntry(int capture_session_id);
+
+ // Find the DeviceEntry that owns a particular controller pointer.
+ DeviceEntry* GetDeviceEntryForController(
+ const VideoCaptureController* controller);
+
bool IsOnDeviceThread() const;
- media::VideoCaptureDevice* GetDeviceInternal(int capture_session_id);
- // The message loop of media stream device thread that this object runs on.
+ // Queries and returns the available device IDs.
+ media::VideoCaptureDevice::Names GetAvailableDevicesOnDeviceThread(
+ MediaStreamType stream_type);
+
+ // Create and Start a new VideoCaptureDevice, storing the result in
+ // |entry->video_capture_device|. Ownership of |handler| passes to
+ // the device.
+ void DoStartDeviceOnDeviceThread(
+ DeviceEntry* entry,
+ const media::VideoCaptureCapability& capture_params,
+ scoped_ptr<media::VideoCaptureDevice::EventHandler> handler);
+
+ // Stop and destroy the VideoCaptureDevice held in
+ // |entry->video_capture_device|.
+ void DoStopDeviceOnDeviceThread(DeviceEntry* entry);
+
+ // The message loop of media stream device thread, where VCD's live.
scoped_refptr<base::MessageLoopProxy> device_loop_;
// Only accessed on Browser::IO thread.
MediaStreamProviderListener* listener_;
int new_capture_session_id_;
- // Only accessed from device thread.
- // VideoCaptureManager owns all VideoCaptureDevices and is responsible for
- // deleting the instances when they are not used any longer.
+ // An entry is kept in this map for every session that has been created via
+ // the Open() entry point. The keys are session_id's. This map is used to
+ // determine which device to use when StartCaptureForClient() occurs. Used
+ // only on the IO thread.
+ std::map<int, MediaStreamDevice> sessions_;
+
+ // An entry, kept in a map, that owns a VideoCaptureDevice and its associated
+ // VideoCaptureController. VideoCaptureManager owns all VideoCaptureDevices
+ // and VideoCaptureControllers and is responsible for deleting the instances
+ // when they are not used any longer.
+ //
+ // The set of currently started VideoCaptureDevice and VideoCaptureController
+ // objects is only accessed from IO thread, though the DeviceEntry instances
+ // themselves may visit to the device thread for device creation and
+ // destruction.
struct DeviceEntry {
- MediaStreamType stream_type;
- media::VideoCaptureDevice* capture_device; // Maybe shared across sessions.
+ DeviceEntry(MediaStreamType stream_type,
+ const std::string& id,
+ scoped_ptr<VideoCaptureController> controller);
+ ~DeviceEntry();
+
+ const MediaStreamType stream_type;
+ const std::string id;
+
+ // The controller. Only used from the IO thread.
+ scoped_ptr<VideoCaptureController> video_capture_controller;
+
+ // The capture device. Only used from the device thread.
+ scoped_ptr<media::VideoCaptureDevice> video_capture_device;
};
- typedef std::map<int, DeviceEntry> VideoCaptureDevices;
- VideoCaptureDevices devices_; // Maps capture_session_id to DeviceEntry.
+ 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.
+ // 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_;
- // Only accessed from device thread.
- // VideoCaptureManager owns all VideoCaptureController's and is responsible
- // for deleting the instances when they are not used any longer.
- // VideoCaptureDevice is one-to-one mapped to VideoCaptureController.
- typedef std::map<media::VideoCaptureDevice*, Controller*> Controllers;
- Controllers controllers_;
-
- // We cache the enumerated video capture devices in GetAvailableDevices
- // (e.g. called by OnEnumerateDevices) and then look up the requested ID when
- // a device is opened (see OnOpen).
- // Used only on the device thread.
+ // 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_;
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 83c064655ed..34172d78cb4 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
@@ -10,8 +10,10 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/renderer_host/media/media_stream_provider.h"
+#include "content/browser/renderer_host/media/video_capture_controller_event_handler.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "content/common/media/media_stream_options.h"
#include "media/video/capture/video_capture_device.h"
@@ -40,30 +42,33 @@ class MockMediaStreamProviderListener : public MediaStreamProviderListener {
MediaStreamProviderError));
}; // class MockMediaStreamProviderListener
-// Needed as an input argument to Start().
-class MockFrameObserver : public media::VideoCaptureDevice::EventHandler {
+// Needed as an input argument to StartCaptureForClient().
+class MockFrameObserver : public VideoCaptureControllerEventHandler {
public:
- virtual scoped_refptr<media::VideoFrame> ReserveOutputBuffer() OVERRIDE {
- return NULL;
- }
- virtual void OnError() OVERRIDE {}
+ MOCK_METHOD1(OnError, void(const VideoCaptureControllerID& id));
+
+ 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(
- const media::VideoCaptureCapability& info) 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 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 {};
+
+ void OnGotControllerCallback(VideoCaptureControllerID) {}
};
// Test class
class VideoCaptureManagerTest : public testing::Test {
public:
- VideoCaptureManagerTest() {}
+ VideoCaptureManagerTest() : next_client_id_(1) {}
virtual ~VideoCaptureManagerTest() {}
protected:
@@ -80,6 +85,48 @@ class VideoCaptureManagerTest : public testing::Test {
virtual void TearDown() OVERRIDE {}
+ void OnGotControllerCallback(
+ VideoCaptureControllerID id,
+ base::Closure quit_closure,
+ bool expect_success,
+ const base::WeakPtr<VideoCaptureController>& controller) {
+ if (expect_success) {
+ ASSERT_TRUE(controller);
+ ASSERT_TRUE(0 == controllers_.count(id));
+ controllers_[id] = controller.get();
+ } else {
+ ASSERT_TRUE(NULL == controller);
+ }
+ quit_closure.Run();
+ }
+
+ 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;
+
+ VideoCaptureControllerID client_id(next_client_id_++);
+ base::RunLoop run_loop;
+ vcm_->StartCaptureForClient(
+ params, base::kNullProcessHandle, client_id, frame_observer_.get(),
+ base::Bind(&VideoCaptureManagerTest::OnGotControllerCallback,
+ base::Unretained(this), client_id, run_loop.QuitClosure(),
+ expect_success));
+ run_loop.Run();
+ return client_id;
+ }
+
+ void StopClient(VideoCaptureControllerID client_id) {
+ ASSERT_TRUE(1 == controllers_.count(client_id));
+ vcm_->StopCaptureForClient(controllers_[client_id], client_id,
+ frame_observer_.get());
+ controllers_.erase(client_id);
+ }
+
+ int next_client_id_;
+ std::map<VideoCaptureControllerID, VideoCaptureController*> controllers_;
scoped_refptr<VideoCaptureManager> vcm_;
scoped_ptr<MockMediaStreamProviderListener> listener_;
scoped_ptr<base::MessageLoop> message_loop_;
@@ -108,15 +155,9 @@ TEST_F(VideoCaptureManagerTest, CreateAndClose) {
message_loop_->RunUntilIdle();
int video_session_id = vcm_->Open(devices.front());
+ VideoCaptureControllerID client_id = StartClient(video_session_id, true);
- media::VideoCaptureParams capture_params;
- capture_params.session_id = video_session_id;
- capture_params.width = 320;
- capture_params.height = 240;
- capture_params.frame_per_second = 30;
- vcm_->Start(capture_params, frame_observer_.get());
-
- vcm_->Stop(video_session_id, base::Closure());
+ StopClient(client_id);
vcm_->Close(video_session_id);
// Wait to check callbacks before removing the listener.
@@ -190,9 +231,9 @@ TEST_F(VideoCaptureManagerTest, OpenNotExisting) {
InSequence s;
EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _))
.Times(1).WillOnce(SaveArg<1>(&devices));
- EXPECT_CALL(*listener_, Error(MEDIA_DEVICE_VIDEO_CAPTURE,
- _, kDeviceNotAvailable))
- .Times(1);
+ EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
+ EXPECT_CALL(*frame_observer_, OnError(_)).Times(1);
+ EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
@@ -204,11 +245,15 @@ TEST_F(VideoCaptureManagerTest, OpenNotExisting) {
std::string device_id("id_doesnt_exist");
StreamDeviceInfo dummy_device(stream_type, device_name, device_id, false);
- // This should fail with error code 'kDeviceNotAvailable'.
- vcm_->Open(dummy_device);
+ // This should fail with an error to the controller.
+ int session_id = vcm_->Open(dummy_device);
+ VideoCaptureControllerID client_id = StartClient(session_id, true);
+ message_loop_->RunUntilIdle();
- // Wait to check callbacks before removing the listener.
+ StopClient(client_id);
+ vcm_->Close(session_id);
message_loop_->RunUntilIdle();
+
vcm_->Unregister();
}
@@ -218,17 +263,21 @@ TEST_F(VideoCaptureManagerTest, StartUsingId) {
EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
- media::VideoCaptureParams capture_params;
- capture_params.session_id = VideoCaptureManager::kStartOpenSessionId;
- capture_params.width = 320;
- capture_params.height = 240;
- capture_params.frame_per_second = 30;
-
// Start shall trigger the Open callback.
- vcm_->Start(capture_params, frame_observer_.get());
+ VideoCaptureControllerID client_id = StartClient(
+ VideoCaptureManager::kStartOpenSessionId, true);
// Stop shall trigger the Close callback
- vcm_->Stop(VideoCaptureManager::kStartOpenSessionId, base::Closure());
+ 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);
// Wait to check callbacks before removing the listener.
message_loop_->RunUntilIdle();
@@ -252,17 +301,12 @@ TEST_F(VideoCaptureManagerTest, CloseWithoutStop) {
int video_session_id = vcm_->Open(devices.front());
- media::VideoCaptureParams capture_params;
- capture_params.session_id = video_session_id;
- capture_params.width = 320;
- capture_params.height = 240;
- capture_params.frame_per_second = 30;
- vcm_->Start(capture_params, frame_observer_.get());
+ VideoCaptureControllerID client_id = StartClient(video_session_id, true);
// Close will stop the running device, an assert will be triggered in
// VideoCaptureManager destructor otherwise.
vcm_->Close(video_session_id);
- vcm_->Stop(video_session_id, base::Closure());
+ StopClient(client_id);
// Wait to check callbacks before removing the listener
message_loop_->RunUntilIdle();
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 e27b703081e..91feb4d4873 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
@@ -56,8 +56,8 @@
#include "base/basictypes.h"
#include "base/bind.h"
-#include "base/bind_helpers.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"
@@ -693,7 +693,7 @@ void RenderVideoFrame(const SkBitmap& input,
}
// The result is now ready.
- failure_handler.Release();
+ ignore_result(failure_handler.Release());
done_cb.Run(true);
}
@@ -1076,7 +1076,7 @@ void WebContentsVideoCaptureDevice::Impl::Allocate(
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::VideoCaptureCapability::kI420;
+ settings.color = media::PIXEL_FORMAT_I420;
settings.expected_capture_delay = 0;
settings.interlaced = false;
@@ -1228,7 +1228,7 @@ WebContentsVideoCaptureDevice::~WebContentsVideoCaptureDevice() {
}
// static
-media::VideoCaptureDevice* WebContentsVideoCaptureDevice::Create(
+media::VideoCaptureDevice1* WebContentsVideoCaptureDevice::Create(
const std::string& device_id) {
// Parse device_id into render_process_id and render_view_id.
int render_process_id = -1;
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 94ac0680f6f..0dfe1d6e2f0 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
@@ -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::VideoCaptureDevice {
+ : public media::VideoCaptureDevice1 {
public:
// Construct from a |device_id| string of the form:
// "virtual-media-stream://render_process_id:render_view_id", where
@@ -37,7 +37,7 @@ 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::VideoCaptureDevice* Create(const std::string& device_id);
+ static media::VideoCaptureDevice1* Create(const std::string& device_id);
virtual ~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 d88d553fa73..3420b09eb7b 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
@@ -310,8 +310,10 @@ class StubConsumer : public media::VideoCaptureDevice::EventHandler {
StubConsumer()
: error_encountered_(false),
wait_color_yuv_(0xcafe1950) {
- buffer_pool_ =
- new VideoCaptureBufferPool(kTestWidth * kTestHeight * 3 / 2, 2);
+ buffer_pool_ = new VideoCaptureBufferPool(
+ media::VideoFrame::AllocationSize(media::VideoFrame::I420,
+ gfx::Size(kTestWidth, kTestHeight)),
+ 2);
EXPECT_TRUE(buffer_pool_->Allocate());
}
virtual ~StubConsumer() {}
@@ -405,7 +407,7 @@ class StubConsumer : public media::VideoCaptureDevice::EventHandler {
EXPECT_EQ(kTestWidth, info.width);
EXPECT_EQ(kTestHeight, info.height);
EXPECT_EQ(kTestFramesPerSecond, info.frame_rate);
- EXPECT_EQ(media::VideoCaptureCapability::kI420, info.color);
+ EXPECT_EQ(media::PIXEL_FORMAT_I420, info.color);
}
private:
@@ -491,7 +493,7 @@ class WebContentsVideoCaptureDeviceTest : public testing::Test {
// Accessors.
CaptureTestSourceController* source() { return &controller_; }
- media::VideoCaptureDevice* device() { return device_.get(); }
+ media::VideoCaptureDevice1* device() { return device_.get(); }
StubConsumer* consumer() { return &consumer_; }
void SimulateDrawEvent() {
@@ -530,7 +532,7 @@ class WebContentsVideoCaptureDeviceTest : public testing::Test {
scoped_ptr<WebContents> web_contents_;
// Finally, the WebContentsVideoCaptureDevice under test.
- scoped_ptr<media::VideoCaptureDevice> device_;
+ scoped_ptr<media::VideoCaptureDevice1> device_;
TestBrowserThreadBundle thread_bundle_;
};
@@ -545,7 +547,7 @@ TEST_F(WebContentsVideoCaptureDeviceTest, InvalidInitialWebContentsError) {
kTestWidth,
kTestHeight,
kTestFramesPerSecond,
- media::VideoCaptureCapability::kI420,
+ media::PIXEL_FORMAT_I420,
0,
false,
media::ConstantResolutionVideoCaptureDevice);
@@ -562,7 +564,7 @@ TEST_F(WebContentsVideoCaptureDeviceTest, WebContentsDestroyed) {
kTestWidth,
kTestHeight,
kTestFramesPerSecond,
- media::VideoCaptureCapability::kI420,
+ media::PIXEL_FORMAT_I420,
0,
false,
media::ConstantResolutionVideoCaptureDevice);
@@ -591,7 +593,7 @@ TEST_F(WebContentsVideoCaptureDeviceTest,
kTestWidth,
kTestHeight,
kTestFramesPerSecond,
- media::VideoCaptureCapability::kI420,
+ media::PIXEL_FORMAT_I420,
0,
false,
media::ConstantResolutionVideoCaptureDevice);
@@ -617,7 +619,7 @@ TEST_F(WebContentsVideoCaptureDeviceTest, StopWithRendererWorkToDo) {
kTestWidth,
kTestHeight,
kTestFramesPerSecond,
- media::VideoCaptureCapability::kI420,
+ media::PIXEL_FORMAT_I420,
0,
false,
media::ConstantResolutionVideoCaptureDevice);
@@ -647,7 +649,7 @@ TEST_F(WebContentsVideoCaptureDeviceTest, DeviceRestart) {
kTestWidth,
kTestHeight,
kTestFramesPerSecond,
- media::VideoCaptureCapability::kI420,
+ media::PIXEL_FORMAT_I420,
0,
false,
media::ConstantResolutionVideoCaptureDevice);
@@ -689,7 +691,7 @@ TEST_F(WebContentsVideoCaptureDeviceTest, GoesThroughAllTheMotions) {
kTestWidth,
kTestHeight,
kTestFramesPerSecond,
- media::VideoCaptureCapability::kI420,
+ media::PIXEL_FORMAT_I420,
0,
false,
media::ConstantResolutionVideoCaptureDevice);
@@ -745,13 +747,13 @@ TEST_F(WebContentsVideoCaptureDeviceTest, RejectsInvalidAllocateParams) {
1280,
720,
-2,
- media::VideoCaptureCapability::kI420,
+ media::PIXEL_FORMAT_I420,
0,
false,
media::ConstantResolutionVideoCaptureDevice);
BrowserThread::PostTask(BrowserThread::UI,
FROM_HERE,
- base::Bind(&media::VideoCaptureDevice::Allocate,
+ base::Bind(&media::VideoCaptureDevice1::Allocate,
base::Unretained(device()),
capture_format,
consumer()));
@@ -763,7 +765,7 @@ TEST_F(WebContentsVideoCaptureDeviceTest, BadFramesGoodFrames) {
kTestWidth,
kTestHeight,
kTestFramesPerSecond,
- media::VideoCaptureCapability::kI420,
+ media::PIXEL_FORMAT_I420,
0,
false,
media::ConstantResolutionVideoCaptureDevice);
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 0230b26eeaa..76c536baf7c 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
@@ -36,13 +36,14 @@ bool WebRTCIdentityServiceHost::OnMessageReceived(const IPC::Message& message,
}
void WebRTCIdentityServiceHost::OnRequestIdentity(
+ int sequence_number,
const GURL& origin,
const std::string& identity_name,
const std::string& common_name) {
if (!cancel_callback_.is_null()) {
DLOG(WARNING)
<< "Request rejected because the previous request has not finished.";
- SendErrorMessage(net::ERR_INSUFFICIENT_RESOURCES);
+ SendErrorMessage(sequence_number, net::ERR_INSUFFICIENT_RESOURCES);
return;
}
@@ -50,7 +51,7 @@ void WebRTCIdentityServiceHost::OnRequestIdentity(
ChildProcessSecurityPolicyImpl::GetInstance();
if (!policy->CanAccessCookiesForOrigin(renderer_process_id_, origin)) {
DLOG(WARNING) << "Request rejected because origin access is denied.";
- SendErrorMessage(net::ERR_ACCESS_DENIED);
+ SendErrorMessage(sequence_number, net::ERR_ACCESS_DENIED);
return;
}
@@ -59,9 +60,10 @@ void WebRTCIdentityServiceHost::OnRequestIdentity(
identity_name,
common_name,
base::Bind(&WebRTCIdentityServiceHost::OnComplete,
- base::Unretained(this)));
+ base::Unretained(this),
+ sequence_number));
if (cancel_callback_.is_null()) {
- SendErrorMessage(net::ERR_UNEXPECTED);
+ SendErrorMessage(sequence_number, net::ERR_UNEXPECTED);
}
}
@@ -69,19 +71,22 @@ void WebRTCIdentityServiceHost::OnCancelRequest() {
base::ResetAndReturn(&cancel_callback_).Run();
}
-void WebRTCIdentityServiceHost::OnComplete(int status,
- const std::string& certificate,
- const std::string& private_key) {
+void WebRTCIdentityServiceHost::OnComplete(int sequence_number,
+ int status,
+ const std::string& certificate,
+ const std::string& private_key) {
cancel_callback_.Reset();
if (status == net::OK) {
- Send(new WebRTCIdentityHostMsg_IdentityReady(certificate, private_key));
+ Send(new WebRTCIdentityHostMsg_IdentityReady(
+ sequence_number, certificate, private_key));
} else {
- SendErrorMessage(status);
+ SendErrorMessage(sequence_number, status);
}
}
-void WebRTCIdentityServiceHost::SendErrorMessage(int error) {
- Send(new WebRTCIdentityHostMsg_RequestFailed(error));
+void WebRTCIdentityServiceHost::SendErrorMessage(int sequence_number,
+ int error) {
+ Send(new WebRTCIdentityHostMsg_RequestFailed(sequence_number, error));
}
} // namespace content
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 3676223fe86..3a5921c5c2d 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
@@ -37,19 +37,26 @@ class CONTENT_EXPORT WebRTCIdentityServiceHost : public BrowserMessageFilter {
bool* message_was_ok) OVERRIDE;
private:
+ // |sequence_number| is the same as in the OnRequestIdentity call.
// See WebRTCIdentityStore for the meaning of the parameters.
- void OnComplete(int status,
+ void OnComplete(int sequence_number,
+ int status,
const std::string& certificate,
const std::string& private_key);
- // See WebRTCIdentityStore for the meaning of the parameters.
- void OnRequestIdentity(const GURL& origin,
+ // |sequence_number| is a renderer wide unique number for each request and
+ // will be echoed in the response to handle the possibility that the renderer
+ // cancels the request after the browser sends the response and before it's
+ // received by the renderer.
+ // See WebRTCIdentityStore for the meaning of the other parameters.
+ void OnRequestIdentity(int sequence_number,
+ const GURL& origin,
const std::string& identity_name,
const std::string& common_name);
void OnCancelRequest();
- void SendErrorMessage(int error);
+ void SendErrorMessage(int sequence_number, int error);
int renderer_process_id_;
base::Closure cancel_callback_;
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 341378d3c7b..cbedf512bc5 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
@@ -24,6 +24,7 @@ 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 int FAKE_SEQUENCE_NUMBER = 1;
class MockWebRTCIdentityStore : public WebRTCIdentityStore {
public:
@@ -105,8 +106,10 @@ class WebRTCIdentityServiceHostTest : public ::testing::Test {
void SendRequestToHost() {
bool ok;
host_->OnMessageReceived(
- WebRTCIdentityMsg_RequestIdentity(
- GURL(FAKE_ORIGIN), FAKE_IDENTITY_NAME, FAKE_COMMON_NAME),
+ WebRTCIdentityMsg_RequestIdentity(FAKE_SEQUENCE_NUMBER,
+ GURL(FAKE_ORIGIN),
+ FAKE_IDENTITY_NAME,
+ FAKE_COMMON_NAME),
&ok);
ASSERT_TRUE(ok);
}
@@ -122,9 +125,10 @@ class WebRTCIdentityServiceHostTest : public ::testing::Test {
IPC::Message ipc = host_->GetLastMessage();
EXPECT_EQ(ipc.type(), WebRTCIdentityHostMsg_RequestFailed::ID);
- Tuple1<int> error_in_message;
+ Tuple2<int, int> error_in_message;
WebRTCIdentityHostMsg_RequestFailed::Read(&ipc, &error_in_message);
- EXPECT_EQ(error, error_in_message.a);
+ EXPECT_EQ(FAKE_SEQUENCE_NUMBER, error_in_message.a);
+ EXPECT_EQ(error, error_in_message.b);
}
void VerifyIdentityReadyMessage(const std::string& cert,
@@ -133,10 +137,11 @@ class WebRTCIdentityServiceHostTest : public ::testing::Test {
IPC::Message ipc = host_->GetLastMessage();
EXPECT_EQ(ipc.type(), WebRTCIdentityHostMsg_IdentityReady::ID);
- Tuple2<std::string, std::string> identity_in_message;
+ Tuple3<int, std::string, std::string> identity_in_message;
WebRTCIdentityHostMsg_IdentityReady::Read(&ipc, &identity_in_message);
- EXPECT_EQ(cert, identity_in_message.a);
- EXPECT_EQ(key, identity_in_message.b);
+ EXPECT_EQ(FAKE_SEQUENCE_NUMBER, identity_in_message.a);
+ EXPECT_EQ(cert, identity_in_message.b);
+ EXPECT_EQ(key, identity_in_message.c);
}
protected:
diff --git a/chromium/content/browser/renderer_host/native_web_keyboard_event.cc b/chromium/content/browser/renderer_host/native_web_keyboard_event.cc
index 3cb2af1397b..646b358ac8d 100644
--- a/chromium/content/browser/renderer_host/native_web_keyboard_event.cc
+++ b/chromium/content/browser/renderer_host/native_web_keyboard_event.cc
@@ -4,7 +4,7 @@
#include "content/public/browser/native_web_keyboard_event.h"
-#include "ui/base/events/event_constants.h"
+#include "ui/events/event_constants.h"
namespace content {
diff --git a/chromium/content/browser/renderer_host/native_web_keyboard_event_aura.cc b/chromium/content/browser/renderer_host/native_web_keyboard_event_aura.cc
index 1658d8d3dc2..ad3aae357cb 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
@@ -6,7 +6,7 @@
#include "base/logging.h"
#include "content/browser/renderer_host/web_input_event_aura.h"
-#include "ui/base/events/event.h"
+#include "ui/events/event.h"
namespace {
@@ -77,7 +77,8 @@ NativeWebKeyboardEvent::NativeWebKeyboardEvent(
nativeKeyCode = character;
text[0] = character;
unmodifiedText[0] = character;
- isSystemKey = (state & ui::EF_ALT_DOWN) != 0;
+ isSystemKey =
+ (state & ui::EF_ALT_DOWN) != 0 && (state & ui::EF_ALTGR_DOWN) == 0;
setKeyIdentifierFromWindowsKeyCode();
}
diff --git a/chromium/content/browser/renderer_host/native_web_keyboard_event_gtk.cc b/chromium/content/browser/renderer_host/native_web_keyboard_event_gtk.cc
index f7631945fec..74ce6a36cbb 100644
--- a/chromium/content/browser/renderer_host/native_web_keyboard_event_gtk.cc
+++ b/chromium/content/browser/renderer_host/native_web_keyboard_event_gtk.cc
@@ -6,9 +6,7 @@
#include <gdk/gdk.h>
-#include "third_party/WebKit/public/web/gtk/WebInputEventFactory.h"
-
-using WebKit::WebInputEventFactory;
+#include "content/browser/renderer_host/input/web_input_event_builders_gtk.h"
namespace {
@@ -32,7 +30,7 @@ NativeWebKeyboardEvent::NativeWebKeyboardEvent()
}
NativeWebKeyboardEvent::NativeWebKeyboardEvent(gfx::NativeEvent native_event)
- : WebKeyboardEvent(WebInputEventFactory::keyboardEvent(&native_event->key)),
+ : WebKeyboardEvent(WebKeyboardEventBuilder::Build(&native_event->key)),
skip_in_browser(false),
match_edit_command(false) {
CopyEventTo(native_event, &os_event);
@@ -41,9 +39,9 @@ NativeWebKeyboardEvent::NativeWebKeyboardEvent(gfx::NativeEvent native_event)
NativeWebKeyboardEvent::NativeWebKeyboardEvent(wchar_t character,
int state,
double time_stamp_seconds)
- : WebKeyboardEvent(WebInputEventFactory::keyboardEvent(character,
- state,
- time_stamp_seconds)),
+ : WebKeyboardEvent(WebKeyboardEventBuilder::Build(character,
+ state,
+ time_stamp_seconds)),
os_event(NULL),
skip_in_browser(false),
match_edit_command(false) {
diff --git a/chromium/content/browser/renderer_host/overscroll_configuration.cc b/chromium/content/browser/renderer_host/overscroll_configuration.cc
index 77585e5fb02..f7c5579f56f 100644
--- a/chromium/content/browser/renderer_host/overscroll_configuration.cc
+++ b/chromium/content/browser/renderer_host/overscroll_configuration.cc
@@ -11,7 +11,8 @@ namespace {
float g_horiz_threshold_complete = 0.25f;
float g_vert_threshold_complete = 0.20f;
-float g_horiz_threshold_start = 50.f;
+float g_horiz_threshold_start_touchscreen = 50.f;
+float g_horiz_threshold_start_touchpad = 50.f;
float g_vert_threshold_start = 0.f;
float g_horiz_resist_after = 30.f;
@@ -31,8 +32,12 @@ void SetOverscrollConfig(OverscrollConfig config, float value) {
g_vert_threshold_complete = value;
break;
- case OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START:
- g_horiz_threshold_start = value;
+ case OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN:
+ g_horiz_threshold_start_touchscreen = value;
+ break;
+
+ case OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHPAD:
+ g_horiz_threshold_start_touchpad = value;
break;
case OVERSCROLL_CONFIG_VERT_THRESHOLD_START:
@@ -61,8 +66,11 @@ float GetOverscrollConfig(OverscrollConfig config) {
case OVERSCROLL_CONFIG_VERT_THRESHOLD_COMPLETE:
return g_vert_threshold_complete;
- case OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START:
- return g_horiz_threshold_start;
+ case OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN:
+ return g_horiz_threshold_start_touchscreen;
+
+ case OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHPAD:
+ return g_horiz_threshold_start_touchpad;
case OVERSCROLL_CONFIG_VERT_THRESHOLD_START:
return g_vert_threshold_start;
diff --git a/chromium/content/browser/renderer_host/overscroll_controller.cc b/chromium/content/browser/renderer_host/overscroll_controller.cc
index 3fed4c332a7..f07efab61f4 100644
--- a/chromium/content/browser/renderer_host/overscroll_controller.cc
+++ b/chromium/content/browser/renderer_host/overscroll_controller.cc
@@ -9,6 +9,8 @@
#include "content/public/browser/overscroll_configuration.h"
#include "content/public/browser/render_widget_host_view.h"
+using WebKit::WebInputEvent;
+
namespace content {
OverscrollController::OverscrollController(
@@ -62,23 +64,25 @@ 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.
- // Send the event through the host when appropriate.
- if (ShouldForwardToHost(event)) {
+ if (WebKit::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 false;
+ return true;
}
if (overscroll_mode_ != OVERSCROLL_NONE && DispatchEventResetsState(event)) {
SetOverscrollMode(OVERSCROLL_NONE);
- // The overscroll gesture status is being reset. If the event is a
- // gesture event (from either touchscreen or trackpad), then make sure the
- // host gets the event first (if it didn't already process it).
- if (ShouldForwardToHost(event)) {
+ if (WebKit::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(
@@ -90,16 +94,9 @@ bool OverscrollController::WillDispatchEvent(
}
if (overscroll_mode_ != OVERSCROLL_NONE) {
- // Consume the event and update overscroll state when in the middle of the
- // overscroll gesture.
- ProcessEventForOverscroll(event);
-
- if (event.type == WebKit::WebInputEvent::TouchEnd ||
- event.type == WebKit::WebInputEvent::TouchCancel ||
- event.type == WebKit::WebInputEvent::TouchMove) {
- return true;
- }
- return false;
+ // Consume the event only if it updates the overscroll state.
+ if (ProcessEventForOverscroll(event))
+ return false;
}
return true;
@@ -224,24 +221,29 @@ bool OverscrollController::DispatchEventResetsState(
}
}
-void OverscrollController::ProcessEventForOverscroll(
+bool OverscrollController::ProcessEventForOverscroll(
const WebKit::WebInputEvent& event) {
+ bool event_processed = false;
switch (event.type) {
case WebKit::WebInputEvent::MouseWheel: {
const WebKit::WebMouseWheelEvent& wheel =
static_cast<const WebKit::WebMouseWheelEvent&>(event);
if (!wheel.hasPreciseScrollingDeltas)
- return;
+ break;
ProcessOverscroll(wheel.deltaX * wheel.accelerationRatioX,
- wheel.deltaY * wheel.accelerationRatioY);
+ wheel.deltaY * wheel.accelerationRatioY,
+ wheel.type);
+ event_processed = true;
break;
}
case WebKit::WebInputEvent::GestureScrollUpdate: {
const WebKit::WebGestureEvent& gesture =
static_cast<const WebKit::WebGestureEvent&>(event);
ProcessOverscroll(gesture.data.scrollUpdate.deltaX,
- gesture.data.scrollUpdate.deltaY);
+ gesture.data.scrollUpdate.deltaY,
+ gesture.type);
+ event_processed = true;
break;
}
case WebKit::WebInputEvent::GestureFlingStart: {
@@ -254,12 +256,14 @@ void OverscrollController::ProcessEventForOverscroll(
if ((overscroll_mode_ == OVERSCROLL_WEST && velocity_x < 0) ||
(overscroll_mode_ == OVERSCROLL_EAST && velocity_x > 0)) {
CompleteAction();
+ event_processed = true;
break;
}
} else if (fabs(velocity_y) > kFlingVelocityThreshold) {
if ((overscroll_mode_ == OVERSCROLL_NORTH && velocity_y < 0) ||
(overscroll_mode_ == OVERSCROLL_SOUTH && velocity_y > 0)) {
CompleteAction();
+ event_processed = true;
break;
}
}
@@ -274,15 +278,20 @@ void OverscrollController::ProcessEventForOverscroll(
WebKit::WebInputEvent::isTouchEventType(event.type))
<< "Received unexpected event: " << event.type;
}
+ return event_processed;
}
-void OverscrollController::ProcessOverscroll(float delta_x, float delta_y) {
+void OverscrollController::ProcessOverscroll(float delta_x,
+ float delta_y,
+ WebKit::WebInputEvent::Type type) {
if (scroll_state_ != STATE_CONTENT_SCROLLING)
overscroll_delta_x_ += delta_x;
overscroll_delta_y_ += delta_y;
float horiz_threshold = GetOverscrollConfig(
- OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START);
+ WebInputEvent::isGestureEventType(type) ?
+ OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN :
+ OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHPAD);
float vert_threshold = GetOverscrollConfig(
OVERSCROLL_CONFIG_VERT_THRESHOLD_START);
if (fabs(overscroll_delta_x_) <= horiz_threshold &&
@@ -359,14 +368,4 @@ void OverscrollController::SetOverscrollMode(OverscrollMode mode) {
delegate_->OnOverscrollModeChange(old_mode, overscroll_mode_);
}
-bool OverscrollController::ShouldForwardToHost(
- const WebKit::WebInputEvent& event) const {
- if (!WebKit::WebInputEvent::isGestureEventType(event.type))
- return false;
-
- // If the RenderWidgetHost already processed this event, then the event must
- // not be sent again.
- return !render_widget_host_->HasQueuedGestureEvents();
-}
-
} // namespace content
diff --git a/chromium/content/browser/renderer_host/overscroll_controller.h b/chromium/content/browser/renderer_host/overscroll_controller.h
index fc1fc5eb47f..fab531947ee 100644
--- a/chromium/content/browser/renderer_host/overscroll_controller.h
+++ b/chromium/content/browser/renderer_host/overscroll_controller.h
@@ -89,13 +89,16 @@ class OverscrollController {
// overscroll gesture status.
bool DispatchEventResetsState(const WebKit::WebInputEvent& event) const;
- // Processes an event and updates internal state for overscroll.
- void ProcessEventForOverscroll(const WebKit::WebInputEvent& event);
+ // 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);
// 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);
+ void ProcessOverscroll(float delta_x,
+ float delta_y,
+ WebKit::WebInputEvent::Type event_type);
// Completes the desired action from the current gesture.
void CompleteAction();
@@ -104,10 +107,6 @@ class OverscrollController {
// appropriate).
void SetOverscrollMode(OverscrollMode new_mode);
- // Returns whether the input event should be forwarded to the
- // RenderWidgetHost.
- bool ShouldForwardToHost(const WebKit::WebInputEvent& event) const;
-
// The RenderWidgetHost that owns this overscroll controller.
RenderWidgetHostImpl* render_widget_host_;
diff --git a/chromium/content/browser/renderer_host/p2p/OWNERS b/chromium/content/browser/renderer_host/p2p/OWNERS
index 17c3a1e6983..f12c2d60e83 100644
--- a/chromium/content/browser/renderer_host/p2p/OWNERS
+++ b/chromium/content/browser/renderer_host/p2p/OWNERS
@@ -1,2 +1,3 @@
-sergeyu@chromium.org
hclam@chromium.org
+mallinath@chromium.org
+sergeyu@chromium.org
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 f1249d51e89..d1a60b451a8 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
@@ -51,7 +51,9 @@ class P2PSocketDispatcherHost::DnsRequest {
net::HostResolver::RequestInfo info(net::HostPortPair(host_name_, 0));
int result = resolver_.Resolve(
- info, &addresses_,
+ info,
+ net::DEFAULT_PRIORITY,
+ &addresses_,
base::Bind(&P2PSocketDispatcherHost::DnsRequest::OnDone,
base::Unretained(this)),
net::BoundNetLog());
@@ -190,8 +192,8 @@ void P2PSocketDispatcherHost::OnCreateSocket(
return;
}
- scoped_ptr<P2PSocketHost> socket(
- P2PSocketHost::Create(this, socket_id, type, url_context_.get()));
+ scoped_ptr<P2PSocketHost> socket(P2PSocketHost::Create(
+ this, socket_id, type, url_context_.get(), &throttler_));
if (!socket) {
Send(new P2PMsg_OnError(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 8a31ae558b1..2369eb2dbea 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h
@@ -7,6 +7,7 @@
#include <map>
+#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"
@@ -84,6 +85,7 @@ class P2PSocketDispatcherHost
bool monitoring_networks_;
std::set<DnsRequest*> dns_requests_;
+ P2PMessageThrottler throttler_;
DISALLOW_COPY_AND_ASSIGN(P2PSocketDispatcherHost);
};
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host.cc b/chromium/content/browser/renderer_host/p2p/socket_host.cc
index 027bf2a608b..4b45e99adad 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host.cc
@@ -15,7 +15,8 @@ const uint32 kStunMagicCookie = 0x2112A442;
namespace content {
-P2PSocketHost::P2PSocketHost(IPC::Sender* message_sender, int id)
+P2PSocketHost::P2PSocketHost(IPC::Sender* message_sender,
+ int id)
: message_sender_(message_sender),
id_(id),
state_(STATE_UNINITIALIZED) {
@@ -73,11 +74,11 @@ bool P2PSocketHost::IsRequestOrResponse(StunMessageType type) {
// static
P2PSocketHost* P2PSocketHost::Create(
IPC::Sender* message_sender, int id, P2PSocketType type,
- net::URLRequestContextGetter* url_context) {
+ net::URLRequestContextGetter* url_context,
+ P2PMessageThrottler* throttler) {
switch (type) {
case P2P_SOCKET_UDP:
- return new P2PSocketHostUdp(message_sender, id);
-
+ return new P2PSocketHostUdp(message_sender, id, throttler);
case P2P_SOCKET_TCP_SERVER:
return new P2PSocketHostTcpServer(
message_sender, id, P2P_SOCKET_TCP_CLIENT);
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host.h b/chromium/content/browser/renderer_host/p2p/socket_host.h
index 8228300408e..fa186c84b49 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_host.h
@@ -7,7 +7,6 @@
#include "content/common/content_export.h"
#include "content/common/p2p_sockets.h"
-
#include "net/base/ip_endpoint.h"
namespace IPC {
@@ -19,6 +18,7 @@ class URLRequestContextGetter;
}
namespace content {
+class P2PMessageThrottler;
// Base class for P2P sockets.
class CONTENT_EXPORT P2PSocketHost {
@@ -27,7 +27,8 @@ class CONTENT_EXPORT P2PSocketHost {
// Creates P2PSocketHost of the specific type.
static P2PSocketHost* Create(IPC::Sender* message_sender,
int id, P2PSocketType type,
- net::URLRequestContextGetter* url_context);
+ net::URLRequestContextGetter* url_context,
+ P2PMessageThrottler* throttler);
virtual ~P2PSocketHost();
@@ -45,6 +46,8 @@ class CONTENT_EXPORT P2PSocketHost {
protected:
friend class P2PSocketHostTcpTestBase;
+ // TODO(mallinath) - Remove this below enum and use one defined in
+ // libjingle/souce/talk/p2p/base/stun.h
enum StunMessageType {
STUN_BINDING_REQUEST = 0x0001,
STUN_BINDING_RESPONSE = 0x0101,
@@ -58,7 +61,15 @@ class CONTENT_EXPORT P2PSocketHost {
STUN_SEND_REQUEST = 0x0004,
STUN_SEND_RESPONSE = 0x0104,
STUN_SEND_ERROR_RESPONSE = 0x0114,
- STUN_DATA_INDICATION = 0x0115
+ STUN_DATA_INDICATION = 0x0115,
+ TURN_SEND_INDICATION = 0x0016,
+ TURN_DATA_INDICATION = 0x0017,
+ TURN_CREATE_PERMISSION_REQUEST = 0x0008,
+ TURN_CREATE_PERMISSION_RESPONSE = 0x0108,
+ TURN_CREATE_PERMISSION_ERROR_RESPONSE = 0x0118,
+ TURN_CHANNEL_BIND_REQUEST = 0x0009,
+ TURN_CHANNEL_BIND_RESPONSE = 0x0109,
+ TURN_CHANNEL_BIND_ERROR_RESPONSE = 0x0119,
};
enum State {
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 8e13bf8f5b5..de9927a7168 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc
@@ -134,18 +134,23 @@ void P2PSocketHostTcpBase::OnConnected(int result) {
if (IsTlsClientSocket(type_)) {
state_ = STATE_TLS_CONNECTING;
StartTls();
- } else {
- if (IsPseudoTlsClientSocket(type_)) {
- socket_.reset(new jingle_glue::FakeSSLClientSocket(socket_.release()));
+ } else if (IsPseudoTlsClientSocket(type_)) {
+ scoped_ptr<net::StreamSocket> transport_socket = socket_.Pass();
+ socket_.reset(
+ new jingle_glue::FakeSSLClientSocket(transport_socket.Pass()));
+ state_ = STATE_TLS_CONNECTING;
+ int status = socket_->Connect(
+ base::Bind(&P2PSocketHostTcpBase::ProcessTlsSslConnectDone,
+ base::Unretained(this)));
+ if (status != net::ERR_IO_PENDING) {
+ ProcessTlsSslConnectDone(status);
}
-
+ } else {
// If we are not doing TLS, we are ready to send data now.
// In case of TLS, SignalConnect will be sent only after TLS handshake is
// successfull. So no buffering will be done at socket handlers if any
// packets sent before that by the application.
- state_ = STATE_OPEN;
- DoSendSocketCreateMsg();
- DoRead();
+ OnOpen();
}
}
@@ -155,7 +160,7 @@ void P2PSocketHostTcpBase::StartTls() {
scoped_ptr<net::ClientSocketHandle> socket_handle(
new net::ClientSocketHandle());
- socket_handle->set_socket(socket_.release());
+ socket_handle->SetSocket(socket_.Pass());
net::SSLClientSocketContext context;
context.cert_verifier = url_context_->GetURLRequestContext()->cert_verifier();
@@ -171,24 +176,27 @@ void P2PSocketHostTcpBase::StartTls() {
net::ClientSocketFactory::GetDefaultFactory();
DCHECK(socket_factory);
- socket_.reset(socket_factory->CreateSSLClientSocket(
- socket_handle.release(), dest_host_port_pair, ssl_config, context));
+ socket_ = socket_factory->CreateSSLClientSocket(
+ socket_handle.Pass(), dest_host_port_pair, ssl_config, context);
int status = socket_->Connect(
- base::Bind(&P2PSocketHostTcpBase::ProcessTlsConnectDone,
+ base::Bind(&P2PSocketHostTcpBase::ProcessTlsSslConnectDone,
base::Unretained(this)));
if (status != net::ERR_IO_PENDING) {
- ProcessTlsConnectDone(status);
+ ProcessTlsSslConnectDone(status);
}
}
-void P2PSocketHostTcpBase::ProcessTlsConnectDone(int status) {
+void P2PSocketHostTcpBase::ProcessTlsSslConnectDone(int status) {
DCHECK_NE(status, net::ERR_IO_PENDING);
DCHECK_EQ(state_, STATE_TLS_CONNECTING);
if (status != net::OK) {
OnError();
return;
}
+ OnOpen();
+}
+void P2PSocketHostTcpBase::OnOpen() {
state_ = STATE_OPEN;
DoSendSocketCreateMsg();
DoRead();
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 e5fa08ff93f..c0047a1c26a 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_tcp.h
@@ -61,7 +61,7 @@ class CONTENT_EXPORT P2PSocketHostTcpBase : public P2PSocketHost {
// SSL/TLS connection functions.
void StartTls();
- void ProcessTlsConnectDone(int status);
+ void ProcessTlsSslConnectDone(int status);
void DidCompleteRead(int result);
void DoRead();
@@ -74,6 +74,8 @@ class CONTENT_EXPORT P2PSocketHostTcpBase : public P2PSocketHost {
void OnRead(int result);
void OnWritten(int result);
+ // Helper method to send socket create message and start read.
+ void OnOpen();
void DoSendSocketCreateMsg();
net::IPEndPoint remote_address_;
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_throttler.cc b/chromium/content/browser/renderer_host/p2p/socket_host_throttler.cc
new file mode 100644
index 00000000000..50a4dd0ac83
--- /dev/null
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_throttler.cc
@@ -0,0 +1,45 @@
+// 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_throttler.h"
+#include "third_party/libjingle/source/talk/base/ratelimiter.h"
+#include "third_party/libjingle/source/talk/base/timing.h"
+
+namespace content {
+
+namespace {
+
+const int kMaxIceMessageBandwidth = 256 * 1024;
+
+} // namespace
+
+
+P2PMessageThrottler::P2PMessageThrottler()
+ : timing_(new talk_base::Timing()),
+ rate_limiter_(new talk_base::RateLimiter(kMaxIceMessageBandwidth, 1.0)) {
+}
+
+P2PMessageThrottler::~P2PMessageThrottler() {
+}
+
+void P2PMessageThrottler::SetTiming(scoped_ptr<talk_base::Timing> timing) {
+ timing_ = timing.Pass();
+}
+
+void P2PMessageThrottler::SetSendIceBandwidth(int bandwidth_kbps) {
+ rate_limiter_.reset(new talk_base::RateLimiter(bandwidth_kbps, 1.0));
+}
+
+bool P2PMessageThrottler::DropNextPacket(size_t packet_len) {
+ double now = timing_->TimerNow();
+ if (!rate_limiter_->CanUse(packet_len, now)) {
+ // Exceeding the send rate, this packet should be dropped.
+ return true;
+ }
+
+ rate_limiter_->Use(packet_len, now);
+ return false;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_throttler.h b/chromium/content/browser/renderer_host/p2p/socket_host_throttler.h
new file mode 100644
index 00000000000..166d30054f5
--- /dev/null
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_throttler.h
@@ -0,0 +1,40 @@
+// 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_P2P_SOCKET_HOST_THROTTLER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_THROTTLER_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+
+namespace talk_base {
+class RateLimiter;
+class Timing;
+}
+
+namespace content {
+
+// A very simple message throtller. User of this class must drop the packet if
+// DropNextPacket returns false for that packet. This method verifies the
+// current sendrate against the required sendrate.
+
+class CONTENT_EXPORT P2PMessageThrottler {
+ public:
+ P2PMessageThrottler();
+ virtual ~P2PMessageThrottler();
+
+ void SetTiming(scoped_ptr<talk_base::Timing> timing);
+ bool DropNextPacket(size_t packet_len);
+ void SetSendIceBandwidth(int bandwith_kbps);
+
+ private:
+ scoped_ptr<talk_base::Timing> timing_;
+ scoped_ptr<talk_base::RateLimiter> rate_limiter_;
+
+ DISALLOW_COPY_AND_ASSIGN(P2PMessageThrottler);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_THROTTLER_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 bcfb282a2c4..54c2b4cd4ed 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_udp.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_udp.cc
@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/debug/trace_event.h"
+#include "content/browser/renderer_host/p2p/socket_host_throttler.h"
#include "content/common/p2p_messages.h"
#include "ipc/ipc_sender.h"
#include "net/base/io_buffer.h"
@@ -61,11 +62,14 @@ P2PSocketHostUdp::PendingPacket::PendingPacket(
P2PSocketHostUdp::PendingPacket::~PendingPacket() {
}
-P2PSocketHostUdp::P2PSocketHostUdp(IPC::Sender* message_sender, int id)
+P2PSocketHostUdp::P2PSocketHostUdp(IPC::Sender* message_sender,
+ int id,
+ P2PMessageThrottler* throttler)
: P2PSocketHost(message_sender, id),
socket_(new net::UDPServerSocket(NULL, net::NetLog::Source())),
send_pending_(false),
- send_packet_count_(0) {
+ send_packet_count_(0),
+ throttler_(throttler) {
}
P2PSocketHostUdp::~P2PSocketHostUdp() {
@@ -180,6 +184,12 @@ void P2PSocketHostUdp::Send(const net::IPEndPoint& to,
OnError();
return;
}
+
+ if (throttler_->DropNextPacket(data.size())) {
+ LOG(INFO) << "STUN message is dropped due to high volume.";
+ // Do not reset socket.
+ return;
+ }
}
if (send_pending_) {
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 e9eb36393f4..befac2cae12 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_udp.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_udp.h
@@ -21,9 +21,12 @@
namespace content {
+class P2PMessageThrottler;
+
class CONTENT_EXPORT P2PSocketHostUdp : public P2PSocketHost {
public:
- P2PSocketHostUdp(IPC::Sender* message_sender, int id);
+ P2PSocketHostUdp(IPC::Sender* message_sender, int id,
+ P2PMessageThrottler* throttler);
virtual ~P2PSocketHostUdp();
// P2PSocketHost overrides.
@@ -71,6 +74,7 @@ class CONTENT_EXPORT P2PSocketHostUdp : public P2PSocketHost {
// Set of peer for which we have received STUN binding request or
// response or relay allocation request or response.
ConnectedPeerSet connected_peers_;
+ P2PMessageThrottler* throttler_;
DISALLOW_COPY_AND_ASSIGN(P2PSocketHostUdp);
};
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 9ecd56abd54..d42efbe3c35 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
@@ -10,12 +10,14 @@
#include "base/logging.h"
#include "base/sys_byteorder.h"
#include "content/browser/renderer_host/p2p/socket_host_test_utils.h"
+#include "content/browser/renderer_host/p2p/socket_host_throttler.h"
#include "net/base/io_buffer.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/udp/datagram_server_socket.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/libjingle/source/talk/base/timing.h"
using ::testing::_;
using ::testing::DeleteArg;
@@ -24,6 +26,16 @@ using ::testing::Return;
namespace {
+class FakeTiming : public talk_base::Timing {
+ public:
+ FakeTiming() : now_(0.0) {}
+ virtual double TimerNow() OVERRIDE { return now_; }
+ void set_now(double now) { now_ = now; }
+
+ private:
+ double now_;
+};
+
class FakeDatagramServerSocket : public net::DatagramServerSocket {
public:
typedef std::pair<net::IPEndPoint, std::vector<char> > UDPPacket;
@@ -161,7 +173,7 @@ class P2PSocketHostUdpTest : public testing::Test {
MatchMessage(static_cast<uint32>(P2PMsg_OnSocketCreated::ID))))
.WillOnce(DoAll(DeleteArg<0>(), Return(true)));
- socket_host_.reset(new P2PSocketHostUdp(&sender_, 0));
+ socket_host_.reset(new P2PSocketHostUdp(&sender_, 0, &throttler_));
socket_ = new FakeDatagramServerSocket(&sent_packets_);
socket_host_->socket_.reset(socket_);
@@ -170,8 +182,12 @@ class P2PSocketHostUdpTest : public testing::Test {
dest1_ = ParseAddress(kTestIpAddress1, kTestPort1);
dest2_ = ParseAddress(kTestIpAddress2, kTestPort2);
+
+ scoped_ptr<talk_base::Timing> timing(new FakeTiming());
+ throttler_.SetTiming(timing.Pass());
}
+ P2PMessageThrottler throttler_;
std::deque<FakeDatagramServerSocket::UDPPacket> sent_packets_;
FakeDatagramServerSocket* socket_; // Owned by |socket_host_|.
scoped_ptr<P2PSocketHostUdp> socket_host_;
@@ -289,4 +305,62 @@ TEST_F(P2PSocketHostUdpTest, SendAfterStunResponseDifferentHost) {
socket_host_->Send(dest2_, packet);
}
+// Verify throttler not allowing unlimited sending of ICE messages to
+// any destination.
+TEST_F(P2PSocketHostUdpTest, ThrottleAfterLimit) {
+ EXPECT_CALL(sender_, Send(
+ MatchMessage(static_cast<uint32>(P2PMsg_OnSendComplete::ID))))
+ .Times(2)
+ .WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
+
+ std::vector<char> packet1;
+ CreateStunRequest(&packet1);
+ throttler_.SetSendIceBandwidth(packet1.size() * 2);
+ socket_host_->Send(dest1_, packet1);
+ socket_host_->Send(dest2_, packet1);
+
+ net::IPEndPoint dest3 = ParseAddress(kTestIpAddress1, 2222);
+ // This packet must be dropped by the throttler.
+ socket_host_->Send(dest3, packet1);
+ ASSERT_EQ(sent_packets_.size(), 2U);
+}
+
+// Verify we can send packets to a known destination when ICE throttling is
+// active.
+TEST_F(P2PSocketHostUdpTest, ThrottleAfterLimitAfterReceive) {
+ // Receive packet from |dest1_|.
+ std::vector<char> request_packet;
+ CreateStunRequest(&request_packet);
+
+ EXPECT_CALL(sender_, Send(MatchPacketMessage(request_packet)))
+ .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
+ socket_->ReceivePacket(dest1_, request_packet);
+
+ EXPECT_CALL(sender_, Send(
+ MatchMessage(static_cast<uint32>(P2PMsg_OnSendComplete::ID))))
+ .Times(4)
+ .WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
+
+ std::vector<char> packet1;
+ CreateStunRequest(&packet1);
+ throttler_.SetSendIceBandwidth(packet1.size());
+ // |dest1_| is known address, throttling will not be applied.
+ socket_host_->Send(dest1_, packet1);
+ // Trying to send the packet to dest1_ in the same window. It should go.
+ socket_host_->Send(dest1_, packet1);
+
+ // Throttler should allow this packet to go through.
+ socket_host_->Send(dest2_, packet1);
+
+ net::IPEndPoint dest3 = ParseAddress(kTestIpAddress1, 2223);
+ // This packet will be dropped, as limit only for a single packet.
+ socket_host_->Send(dest3, packet1);
+ net::IPEndPoint dest4 = ParseAddress(kTestIpAddress1, 2224);
+ // This packet should also be dropped.
+ socket_host_->Send(dest4, packet1);
+ // |dest1| is known, we can send as many packets to it.
+ socket_host_->Send(dest1_, packet1);
+ ASSERT_EQ(sent_packets_.size(), 4U);
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/OWNERS b/chromium/content/browser/renderer_host/pepper/OWNERS
index dc19a03cb21..33d4c55751a 100644
--- a/chromium/content/browser/renderer_host/pepper/OWNERS
+++ b/chromium/content/browser/renderer_host/pepper/OWNERS
@@ -1,3 +1,4 @@
+bbudge@chromium.org
dmichael@chromium.org
raymes@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 10eef8b5515..db3f8eff2ae 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
@@ -4,6 +4,7 @@
#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
+#include "content/browser/renderer_host/pepper/pepper_message_filter.h"
#include "content/browser/tracing/trace_message_filter.h"
#include "content/common/pepper_renderer_instance_data.h"
#include "content/public/browser/render_view_host.h"
@@ -18,23 +19,17 @@ BrowserPpapiHost* BrowserPpapiHost::CreateExternalPluginProcess(
ppapi::PpapiPermissions permissions,
base::ProcessHandle plugin_child_process,
IPC::ChannelProxy* channel,
- net::HostResolver* host_resolver,
int render_process_id,
int render_view_id,
const base::FilePath& profile_directory) {
- scoped_refptr<PepperMessageFilter> pepper_message_filter(
- new PepperMessageFilter(permissions,
- host_resolver,
- render_process_id,
- render_view_id));
-
// 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,
- pepper_message_filter);
+ base::FilePath(), profile_directory, true);
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());
@@ -48,17 +43,17 @@ BrowserPpapiHostImpl::BrowserPpapiHostImpl(
const std::string& plugin_name,
const base::FilePath& plugin_path,
const base::FilePath& profile_data_directory,
- bool external_plugin,
- const scoped_refptr<PepperMessageFilter>& pepper_message_filter)
+ 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),
- external_plugin_(external_plugin) {
+ external_plugin_(external_plugin),
+ ssl_context_helper_(new SSLContextHelper()) {
message_filter_ = new HostMessageFilter(ppapi_host_.get());
ppapi_host_->AddHostFactoryFilter(scoped_ptr<ppapi::host::HostFactory>(
- new ContentBrowserPepperHostFactory(this, pepper_message_filter)));
+ new ContentBrowserPepperHostFactory(this)));
}
BrowserPpapiHostImpl::~BrowserPpapiHostImpl() {
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 c46ab13b220..f16d1d82c18 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
@@ -13,7 +13,7 @@
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h"
-#include "content/browser/renderer_host/pepper/pepper_message_filter.h"
+#include "content/browser/renderer_host/pepper/ssl_context_helper.h"
#include "content/common/content_export.h"
#include "content/common/pepper_renderer_instance_data.h"
#include "content/public/browser/browser_ppapi_host.h"
@@ -36,10 +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 external_plugin,
- // TODO (ygorshenin@): remove this once TCP sockets are
- // converted to the new design.
- const scoped_refptr<PepperMessageFilter>& pepper_message_filter);
+ bool external_plugin);
virtual ~BrowserPpapiHostImpl();
// BrowserPpapiHost.
@@ -72,6 +69,10 @@ class CONTENT_EXPORT BrowserPpapiHostImpl : public BrowserPpapiHost {
return message_filter_;
}
+ const scoped_refptr<SSLContextHelper>& ssl_context_helper() const {
+ return ssl_context_helper_;
+ }
+
private:
friend class BrowserPpapiHostTest;
@@ -103,6 +104,8 @@ class CONTENT_EXPORT BrowserPpapiHostImpl : public BrowserPpapiHost {
// BrowserPpapiHost::CreateExternalPluginProcess.
bool external_plugin_;
+ scoped_refptr<SSLContextHelper> ssl_context_helper_;
+
// Tracks all PP_Instances in this plugin and associated renderer-related
// data.
typedef std::map<PP_Instance, PepperRendererInstanceData> InstanceMap;
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 a8c257abacd..c338a990f59 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,8 +16,7 @@ BrowserPpapiHostTest::BrowserPpapiHostTest()
std::string(),
base::FilePath(),
base::FilePath(),
- false,
- NULL));
+ false));
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 f0cefc40396..39e778dfe6b 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
@@ -11,10 +11,12 @@
#include "content/browser/renderer_host/pepper/pepper_flash_file_message_filter.h"
#include "content/browser/renderer_host/pepper/pepper_gamepad_host.h"
#include "content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.h"
+#include "content/browser/renderer_host/pepper/pepper_network_monitor_host.h"
#include "content/browser/renderer_host/pepper/pepper_network_proxy_host.h"
#include "content/browser/renderer_host/pepper/pepper_print_settings_manager.h"
#include "content/browser/renderer_host/pepper/pepper_printing_host.h"
#include "content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h"
+#include "content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h"
#include "content/browser/renderer_host/pepper/pepper_truetype_font_list_host.h"
#include "content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h"
#include "ppapi/host/message_filter_host.h"
@@ -36,18 +38,17 @@ const size_t kMaxSocketsAllowed = 1024;
bool CanCreateSocket() {
return
- PepperUDPSocketMessageFilter::GetNumInstances() +
- PepperTCPServerSocketMessageFilter::GetNumInstances() <
+ PepperTCPServerSocketMessageFilter::GetNumInstances() +
+ PepperTCPSocketMessageFilter::GetNumInstances() +
+ PepperUDPSocketMessageFilter::GetNumInstances() <
kMaxSocketsAllowed;
}
} // namespace
ContentBrowserPepperHostFactory::ContentBrowserPepperHostFactory(
- BrowserPpapiHostImpl* host,
- const scoped_refptr<PepperMessageFilter>& pepper_message_filter)
- : host_(host),
- pepper_message_filter_(pepper_message_filter) {
+ BrowserPpapiHostImpl* host)
+ : host_(host) {
}
ContentBrowserPepperHostFactory::~ContentBrowserPepperHostFactory() {
@@ -102,6 +103,15 @@ scoped_ptr<ResourceHost> ContentBrowserPepperHostFactory::CreateResourceHost(
return scoped_ptr<ResourceHost>(new PepperFileRefHost(
host_, instance, params.pp_resource(), file_system, internal_path));
}
+ case PpapiHostMsg_TCPSocket_Create::ID: {
+ ppapi::TCPSocketVersion version;
+ if (!UnpackMessage<PpapiHostMsg_TCPSocket_Create>(message, &version) ||
+ version == ppapi::TCP_SOCKET_VERSION_PRIVATE) {
+ return scoped_ptr<ResourceHost>();
+ }
+
+ return CreateNewTCPSocket(instance, params.pp_resource(), version);
+ }
case PpapiHostMsg_UDPSocket_Create::ID: {
if (CanCreateSocket()) {
scoped_refptr<ResourceMessageFilter> udp_socket(
@@ -155,8 +165,7 @@ scoped_ptr<ResourceHost> ContentBrowserPepperHostFactory::CreateResourceHost(
if (message.type() == PpapiHostMsg_TCPServerSocket_CreatePrivate::ID) {
if (CanCreateSocket()) {
scoped_refptr<ResourceMessageFilter> tcp_server_socket(
- new PepperTCPServerSocketMessageFilter(host_, instance, true,
- pepper_message_filter_));
+ new PepperTCPServerSocketMessageFilter(this, host_, instance, true));
return scoped_ptr<ResourceHost>(new MessageFilterHost(
host_->GetPpapiHost(), instance, params.pp_resource(),
tcp_server_socket));
@@ -164,6 +173,10 @@ scoped_ptr<ResourceHost> ContentBrowserPepperHostFactory::CreateResourceHost(
return scoped_ptr<ResourceHost>();
}
}
+ if (message.type() == PpapiHostMsg_TCPSocket_CreatePrivate::ID) {
+ return CreateNewTCPSocket(instance, params.pp_resource(),
+ ppapi::TCP_SOCKET_VERSION_PRIVATE);
+ }
if (message.type() == PpapiHostMsg_UDPSocket_CreatePrivate::ID) {
if (CanCreateSocket()) {
scoped_refptr<ResourceMessageFilter> udp_socket(
@@ -174,6 +187,10 @@ scoped_ptr<ResourceHost> ContentBrowserPepperHostFactory::CreateResourceHost(
return scoped_ptr<ResourceHost>();
}
}
+ if (message.type() == PpapiHostMsg_NetworkMonitor_Create::ID) {
+ return scoped_ptr<ResourceHost>(
+ new PepperNetworkMonitorHost(host_, instance, params.pp_resource()));
+ }
// Flash interfaces.
if (GetPermissions().HasPermission(ppapi::PERMISSION_FLASH)) {
@@ -191,6 +208,37 @@ scoped_ptr<ResourceHost> ContentBrowserPepperHostFactory::CreateResourceHost(
return scoped_ptr<ResourceHost>();
}
+scoped_ptr<ppapi::host::ResourceHost>
+ContentBrowserPepperHostFactory::CreateAcceptedTCPSocket(
+ PP_Instance instance,
+ ppapi::TCPSocketVersion version,
+ scoped_ptr<net::TCPSocket> socket) {
+ if (!CanCreateSocket())
+ return scoped_ptr<ResourceHost>();
+ scoped_refptr<ResourceMessageFilter> tcp_socket(
+ new PepperTCPSocketMessageFilter(host_, instance, version,
+ socket.Pass()));
+ return scoped_ptr<ResourceHost>(new MessageFilterHost(
+ host_->GetPpapiHost(), instance, 0, tcp_socket));
+}
+
+scoped_ptr<ppapi::host::ResourceHost>
+ContentBrowserPepperHostFactory::CreateNewTCPSocket(
+ PP_Instance instance,
+ PP_Resource resource,
+ ppapi::TCPSocketVersion version) {
+ if (!CanCreateSocket())
+ return scoped_ptr<ResourceHost>();
+
+ scoped_refptr<ResourceMessageFilter> tcp_socket(
+ new PepperTCPSocketMessageFilter(this, host_, instance, version));
+ if (!tcp_socket)
+ return scoped_ptr<ResourceHost>();
+
+ return scoped_ptr<ResourceHost>(new MessageFilterHost(
+ host_->GetPpapiHost(), instance, resource, tcp_socket));
+}
+
const ppapi::PpapiPermissions&
ContentBrowserPepperHostFactory::GetPermissions() const {
return host_->GetPpapiHost()->permissions();
diff --git a/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h b/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h
index e39ec35d858..04267a32e8a 100644
--- a/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h
+++ b/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h
@@ -7,8 +7,11 @@
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
-#include "content/browser/renderer_host/pepper/pepper_message_filter.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/socket/tcp_socket.h"
+#include "ppapi/c/pp_resource.h"
#include "ppapi/host/host_factory.h"
+#include "ppapi/shared_impl/ppb_tcp_socket_shared.h"
namespace ppapi {
class PpapiPermissions;
@@ -21,11 +24,8 @@ class BrowserPpapiHostImpl;
class ContentBrowserPepperHostFactory : public ppapi::host::HostFactory {
public:
// Non-owning pointer to the filter must outlive this class.
- ContentBrowserPepperHostFactory(
- BrowserPpapiHostImpl* host,
- // TODO (ygorshenin@): remove this once TCP sockets are
- // converted to the new design.
- const scoped_refptr<PepperMessageFilter>& pepper_message_filter);
+ explicit ContentBrowserPepperHostFactory(BrowserPpapiHostImpl* host);
+
virtual ~ContentBrowserPepperHostFactory();
virtual scoped_ptr<ppapi::host::ResourceHost> CreateResourceHost(
@@ -34,14 +34,24 @@ class ContentBrowserPepperHostFactory : public ppapi::host::HostFactory {
PP_Instance instance,
const IPC::Message& message) OVERRIDE;
+ // Creates ResourceHost for already accepted TCP |socket|. In the case of
+ // failure returns wrapped NULL.
+ scoped_ptr<ppapi::host::ResourceHost> CreateAcceptedTCPSocket(
+ PP_Instance instance,
+ ppapi::TCPSocketVersion version,
+ scoped_ptr<net::TCPSocket> socket);
+
private:
+ scoped_ptr<ppapi::host::ResourceHost> CreateNewTCPSocket(
+ PP_Instance instance,
+ PP_Resource resource,
+ ppapi::TCPSocketVersion version);
+
const ppapi::PpapiPermissions& GetPermissions() const;
// Non-owning pointer.
BrowserPpapiHostImpl* host_;
- scoped_refptr<PepperMessageFilter> pepper_message_filter_;
-
DISALLOW_COPY_AND_ASSIGN(ContentBrowserPepperHostFactory);
};
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 27ba37dfcca..096b908266f 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
@@ -90,21 +90,16 @@ int32_t PepperExternalFileRefBackend::GetAbsolutePath(
ppapi::host::ReplyMessageContext reply_context) {
host_->SendReply(reply_context,
PpapiPluginMsg_FileRef_GetAbsolutePathReply(path_.AsUTF8Unsafe()));
- return PP_OK;
+
+ // Use PP_OK_COMPLETIONPENDING instead of PP_OK since we've already sent our
+ // reply above.
+ return PP_OK_COMPLETIONPENDING;
}
fileapi::FileSystemURL PepperExternalFileRefBackend::GetFileSystemURL() const {
return fileapi::FileSystemURL();
}
-std::string PepperExternalFileRefBackend::GetFileSystemURLSpec() const {
- return std::string();
-}
-
-base::FilePath PepperExternalFileRefBackend::GetExternalPath() const {
- return path_;
-}
-
int32_t PepperExternalFileRefBackend::CanRead() const {
if (!ChildProcessSecurityPolicyImpl::GetInstance()->
CanReadFile(render_process_id_, path_)) {
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 994e9c291cd..cbfaf6ed511 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,8 +41,6 @@ class PepperExternalFileRefBackend : public PepperFileRefBackend {
virtual int32_t GetAbsolutePath(ppapi::host::ReplyMessageContext context)
OVERRIDE;
virtual fileapi::FileSystemURL GetFileSystemURL() const OVERRIDE;
- virtual std::string GetFileSystemURLSpec() const OVERRIDE;
- virtual base::FilePath GetExternalPath() const OVERRIDE;
virtual int32_t CanRead() const OVERRIDE;
virtual int32_t CanWrite() const OVERRIDE;
@@ -68,6 +66,8 @@ class PepperExternalFileRefBackend : public PepperFileRefBackend {
scoped_refptr<base::TaskRunner> task_runner_;
base::WeakPtrFactory<PepperExternalFileRefBackend> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperExternalFileRefBackend);
};
} // namespace content
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 5370af9d853..c38f8826534 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
@@ -62,9 +62,9 @@ PepperFileRefHost::PepperFileRefHost(BrowserPpapiHost* host,
}
fs_type_ = fs_host->GetType();
- // TODO(teravest): Add support for isolated filesystems.
if ((fs_type_ != PP_FILESYSTEMTYPE_LOCALPERSISTENT) &&
- (fs_type_ != PP_FILESYSTEMTYPE_LOCALTEMPORARY)) {
+ (fs_type_ != PP_FILESYSTEMTYPE_LOCALTEMPORARY) &&
+ (fs_type_ != PP_FILESYSTEMTYPE_ISOLATED)) {
DLOG(ERROR) << "Unsupported filesystem type: " << fs_type_;
return;
}
@@ -116,18 +116,6 @@ fileapi::FileSystemURL PepperFileRefHost::GetFileSystemURL() const {
return fileapi::FileSystemURL();
}
-std::string PepperFileRefHost::GetFileSystemURLSpec() const {
- if (backend_)
- return backend_->GetFileSystemURLSpec();
- return std::string();
-}
-
-base::FilePath PepperFileRefHost::GetExternalPath() const {
- if (backend_)
- return backend_->GetExternalPath();
- return base::FilePath();
-}
-
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 5d765764326..b97ff331ac0 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
@@ -42,8 +42,6 @@ class PepperFileRefBackend {
virtual int32_t GetAbsolutePath(
ppapi::host::ReplyMessageContext context) = 0;
virtual fileapi::FileSystemURL GetFileSystemURL() const = 0;
- virtual std::string GetFileSystemURLSpec() const = 0;
- virtual base::FilePath GetExternalPath() const = 0;
// Returns an error from the pp_errors.h enum.
virtual int32_t CanRead() const = 0;
@@ -79,10 +77,6 @@ class CONTENT_EXPORT PepperFileRefHost
PP_FileSystemType GetFileSystemType() const;
fileapi::FileSystemURL GetFileSystemURL() const;
- // Required to support FileIO.
- std::string GetFileSystemURLSpec() const;
- base::FilePath GetExternalPath() const;
-
int32_t CanRead() const;
int32_t CanWrite() const;
int32_t CanCreate() const;
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 1a10da77b83..fce371d8f99 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
@@ -58,16 +58,17 @@ PepperFileSystemBrowserHost::PepperFileSystemBrowserHost(BrowserPpapiHost* host,
PP_FileSystemType type)
: ResourceHost(host->GetPpapiHost(), instance, resource),
browser_ppapi_host_(host),
- weak_factory_(this),
type_(type),
opened_(false),
fs_context_(NULL),
- called_open_(false) {
+ called_open_(false),
+ weak_factory_(this) {
}
PepperFileSystemBrowserHost::~PepperFileSystemBrowserHost() {
- if (fs_context_.get())
- fs_context_->operation_runner()->Shutdown();
+ // TODO(teravest): Create a FileSystemOperationRunner
+ // per-PepperFileSystemBrowserHost, force users of this FileSystem to use it,
+ // and call Shutdown() on it here.
}
int32_t PepperFileSystemBrowserHost::OnResourceMessageReceived(
@@ -151,6 +152,18 @@ void PepperFileSystemBrowserHost::GotFileSystemContext(
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,
@@ -177,7 +190,22 @@ int32_t PepperFileSystemBrowserHost::OnHostMsgInitIsolatedFileSystem(
root_url_ = GURL(fileapi::GetIsolatedFileSystemRootURIString(
url.GetOrigin(), fsid, "crxfs"));
opened_ = true;
- return PP_OK;
+
+ int render_process_id = 0;
+ int unused;
+ if (!browser_ppapi_host_->GetRenderViewIDsForInstance(pp_instance(),
+ &render_process_id,
+ &unused)) {
+ return PP_ERROR_FAILED;
+ }
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&GetFileSystemContextFromRenderId, render_process_id),
+ base::Bind(&PepperFileSystemBrowserHost::GotIsolatedFileSystemContext,
+ weak_factory_.GetWeakPtr(),
+ context->MakeReplyMessageContext()));
+ return PP_OK_COMPLETIONPENDING;
}
} // 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 3eb146e5b7e..ed648fb9938 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
@@ -47,6 +47,9 @@ class PepperFileSystemBrowserHost :
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);
void OpenFileSystemComplete(
ppapi::host::ReplyMessageContext reply_context,
base::PlatformFileError error,
@@ -60,7 +63,6 @@ class PepperFileSystemBrowserHost :
const std::string& fsid);
BrowserPpapiHost* browser_ppapi_host_;
- base::WeakPtrFactory<PepperFileSystemBrowserHost> weak_factory_;
PP_FileSystemType type_;
bool opened_; // whether open is successful.
@@ -68,6 +70,8 @@ class PepperFileSystemBrowserHost :
scoped_refptr<fileapi::FileSystemContext> fs_context_;
bool called_open_; // whether open has been called.
+ base::WeakPtrFactory<PepperFileSystemBrowserHost> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(PepperFileSystemBrowserHost);
};
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc b/chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc
index e0e17b367ed..bdbdf871e27 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc
@@ -132,7 +132,7 @@ int32_t PepperHostResolverMessageFilter::OnMsgResolve(
if (!render_view_host ||
!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
private_api_,
- request,
+ &request,
render_view_host)) {
return PP_ERROR_NOACCESS;
}
@@ -179,6 +179,7 @@ void PepperHostResolverMessageFilter::DoResolve(
new PepperLookupRequest<ReplyMessageContext>(
host_resolver,
request_info,
+ net::DEFAULT_PRIORITY,
bound_info.release(),
base::Bind(&PepperHostResolverMessageFilter::OnLookupFinished, this));
lookup_request->Start();
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 337807d34e1..3b8c801ec1a 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
@@ -63,27 +63,16 @@ fileapi::FileSystemURL PepperInternalFileRefBackend::GetFileSystemURL() const {
if (!fs_url_.is_valid() && fs_host_.get() && fs_host_->IsOpened()) {
GURL fs_path = fs_host_->GetRootUrl().Resolve(
net::EscapePath(path_.substr(1)));
- fs_url_ = GetFileSystemContext()->CrackURL(fs_path);
+ scoped_refptr<fileapi::FileSystemContext> fs_context =
+ GetFileSystemContext();
+ if (fs_context.get())
+ fs_url_ = fs_context->CrackURL(fs_path);
}
return fs_url_;
}
-std::string PepperInternalFileRefBackend::GetFileSystemURLSpec() const {
- if (fs_host_.get() && fs_host_->IsOpened() &&
- fs_host_->GetRootUrl().is_valid()) {
- return fs_host_->GetRootUrl().Resolve(
- net::EscapePath(path_.substr(1))).spec();
- }
- return std::string();
-}
-
-base::FilePath PepperInternalFileRefBackend::GetExternalPath() const {
- return base::FilePath();
-}
-
scoped_refptr<fileapi::FileSystemContext>
PepperInternalFileRefBackend::GetFileSystemContext() const {
- // TODO(teravest): Make this work for CRX file systems.
if (!fs_host_.get())
return NULL;
return fs_host_->GetFileSystemContext();
@@ -221,7 +210,7 @@ void PepperInternalFileRefBackend::ReadDirectoryComplete(
context.params.set_result(ppapi::PlatformFileErrorToPepperError(error));
- std::vector<ppapi::FileRef_CreateInfo> infos;
+ std::vector<ppapi::FileRefCreateInfo> infos;
std::vector<PP_FileType> file_types;
if (error == base::PLATFORM_FILE_OK && fs_host_.get()) {
std::string dir_path = path_;
@@ -235,7 +224,7 @@ void PepperInternalFileRefBackend::ReadDirectoryComplete(
else
file_types.push_back(PP_FILETYPE_REGULAR);
- ppapi::FileRef_CreateInfo info;
+ ppapi::FileRefCreateInfo info;
info.file_system_type = fs_type_;
info.file_system_plugin_resource = fs_host_->pp_resource();
std::string path =
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 fb8a6cf7603..81d6ab624cd 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
@@ -46,8 +46,6 @@ class PepperInternalFileRefBackend : public PepperFileRefBackend {
OVERRIDE;
virtual fileapi::FileSystemURL GetFileSystemURL() const OVERRIDE;
- virtual std::string GetFileSystemURLSpec() const OVERRIDE;
- virtual base::FilePath GetExternalPath() const OVERRIDE;
virtual int32_t CanRead() const OVERRIDE;
virtual int32_t CanWrite() const OVERRIDE;
@@ -82,6 +80,8 @@ class PepperInternalFileRefBackend : public PepperFileRefBackend {
mutable fileapi::FileSystemURL fs_url_;
base::WeakPtrFactory<PepperInternalFileRefBackend> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperInternalFileRefBackend);
};
} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_lookup_request.h b/chromium/content/browser/renderer_host/pepper/pepper_lookup_request.h
index bcb9a60203f..da116fd640c 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_lookup_request.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_lookup_request.h
@@ -24,20 +24,23 @@ class PepperLookupRequest {
// callback, when lookup will finish.
PepperLookupRequest(net::HostResolver* resolver,
const net::HostResolver::RequestInfo& request_info,
+ net::RequestPriority priority,
T* bound_info,
const LookupRequestCallback& callback)
: resolver_(resolver),
request_info_(request_info),
+ priority_(priority),
bound_info_(bound_info),
- callback_(callback) {
- }
+ callback_(callback) {}
void Start() {
- int result = resolver_.Resolve(
- request_info_, &addresses_,
- base::Bind(&PepperLookupRequest<T>::OnLookupFinished,
- base::Unretained(this)),
- net::BoundNetLog());
+ int result =
+ resolver_.Resolve(request_info_,
+ priority_,
+ &addresses_,
+ base::Bind(&PepperLookupRequest<T>::OnLookupFinished,
+ base::Unretained(this)),
+ net::BoundNetLog());
if (result != net::ERR_IO_PENDING)
OnLookupFinished(result);
}
@@ -50,6 +53,7 @@ class PepperLookupRequest {
net::SingleRequestHostResolver resolver_;
net::HostResolver::RequestInfo request_info_;
+ net::RequestPriority priority_;
scoped_ptr<T> bound_info_;
LookupRequestCallback callback_;
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 717de350dc7..6434729b734 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_message_filter.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_message_filter.cc
@@ -4,118 +4,20 @@
#include "content/browser/renderer_host/pepper/pepper_message_filter.h"
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "base/files/file_path.h"
#include "base/logging.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/threading/sequenced_worker_pool.h"
-#include "base/threading/worker_pool.h"
-#include "build/build_config.h"
#include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
-#include "content/browser/renderer_host/pepper/pepper_tcp_socket.h"
-#include "content/browser/renderer_host/render_process_host_impl.h"
-#include "content/browser/renderer_host/render_view_host_impl.h"
-#include "content/common/pepper_messages.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/resource_context.h"
#include "content/public/common/content_client.h"
-#include "net/base/address_family.h"
-#include "net/base/address_list.h"
-#include "net/base/host_port_pair.h"
-#include "net/base/sys_addrinfo.h"
-#include "net/cert/cert_verifier.h"
-#include "ppapi/c/pp_errors.h"
-#include "ppapi/c/private/ppb_net_address_private.h"
#include "ppapi/proxy/ppapi_messages.h"
-#include "ppapi/shared_impl/api_id.h"
-#include "ppapi/shared_impl/private/net_address_private_impl.h"
-#include "ppapi/shared_impl/socket_option_data.h"
-
-using ppapi::NetAddressPrivateImpl;
namespace content {
-namespace {
-
-const size_t kMaxSocketsAllowed = 1024;
-const uint32 kInvalidSocketID = 0;
-
-} // namespace
-PepperMessageFilter::PepperMessageFilter(int process_id,
- BrowserContext* browser_context)
- : plugin_type_(PLUGIN_TYPE_IN_PROCESS),
- permissions_(),
- process_id_(process_id),
- external_plugin_render_view_id_(0),
- resource_context_(browser_context->GetResourceContext()),
- host_resolver_(NULL),
- next_socket_id_(1) {
- DCHECK(browser_context);
- // Keep BrowserContext data in FILE-thread friendly storage.
- browser_path_ = browser_context->GetPath();
- incognito_ = browser_context->IsOffTheRecord();
- DCHECK(resource_context_);
-}
-
-PepperMessageFilter::PepperMessageFilter(
- const ppapi::PpapiPermissions& permissions,
- net::HostResolver* host_resolver)
- : plugin_type_(PLUGIN_TYPE_OUT_OF_PROCESS),
- permissions_(permissions),
- process_id_(0),
- external_plugin_render_view_id_(0),
- resource_context_(NULL),
- host_resolver_(host_resolver),
- next_socket_id_(1),
- incognito_(false) {
- DCHECK(host_resolver);
-}
-
-PepperMessageFilter::PepperMessageFilter(
- const ppapi::PpapiPermissions& permissions,
- net::HostResolver* host_resolver,
- int process_id,
- int render_view_id)
- : plugin_type_(PLUGIN_TYPE_EXTERNAL_PLUGIN),
- permissions_(permissions),
- process_id_(process_id),
- external_plugin_render_view_id_(render_view_id),
- resource_context_(NULL),
- host_resolver_(host_resolver),
- next_socket_id_(1) {
- DCHECK(host_resolver);
-}
+PepperMessageFilter::PepperMessageFilter() {}
+PepperMessageFilter::~PepperMessageFilter() {}
bool PepperMessageFilter::OnMessageReceived(const IPC::Message& msg,
bool* message_was_ok) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP_EX(PepperMessageFilter, msg, *message_was_ok)
- // TCP messages.
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_Create, OnTCPCreate)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_CreatePrivate,
- OnTCPCreatePrivate)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_Connect, OnTCPConnect)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_ConnectWithNetAddress,
- OnTCPConnectWithNetAddress)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_SSLHandshake,
- OnTCPSSLHandshake)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_Read, OnTCPRead)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_Write, OnTCPWrite)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_Disconnect, OnTCPDisconnect)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_SetOption, OnTCPSetOption)
-
- // NetworkMonitor messages.
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBNetworkMonitor_Start,
- OnNetworkMonitorStart)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBNetworkMonitor_Stop,
- OnNetworkMonitorStop)
-
// X509 certificate messages.
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBX509Certificate_ParseDER,
OnX509CertificateParseDER);
@@ -125,367 +27,14 @@ bool PepperMessageFilter::OnMessageReceived(const IPC::Message& msg,
return handled;
}
-void PepperMessageFilter::OnIPAddressChanged() {
- GetAndSendNetworkList();
-}
-
-net::HostResolver* PepperMessageFilter::GetHostResolver() {
- return resource_context_ ?
- resource_context_->GetHostResolver() : host_resolver_;
-}
-
-net::CertVerifier* PepperMessageFilter::GetCertVerifier() {
- if (!cert_verifier_)
- cert_verifier_.reset(net::CertVerifier::CreateDefault());
-
- return cert_verifier_.get();
-}
-
-net::TransportSecurityState* PepperMessageFilter::GetTransportSecurityState() {
- if (!transport_security_state_)
- transport_security_state_.reset(new net::TransportSecurityState);
-
- return transport_security_state_.get();
-}
-
-uint32 PepperMessageFilter::AddAcceptedTCPSocket(
- int32 routing_id,
- uint32 plugin_dispatcher_id,
- net::StreamSocket* socket) {
- scoped_ptr<net::StreamSocket> s(socket);
-
- uint32 tcp_socket_id = GenerateSocketID();
- if (tcp_socket_id != kInvalidSocketID) {
- // Currently all TCP sockets created this way correspond to
- // PPB_TCPSocket_Private.
- tcp_sockets_[tcp_socket_id] = linked_ptr<PepperTCPSocket>(
- new PepperTCPSocket(this,
- routing_id,
- plugin_dispatcher_id,
- tcp_socket_id,
- s.release(),
- true /* private_api */));
- }
- return tcp_socket_id;
-}
-
-PepperMessageFilter::~PepperMessageFilter() {
- if (!network_monitor_ids_.empty())
- net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
-}
-
-void PepperMessageFilter::OnTCPCreate(int32 routing_id,
- uint32 plugin_dispatcher_id,
- uint32* socket_id) {
- CreateTCPSocket(routing_id, plugin_dispatcher_id, false, socket_id);
-}
-
-void PepperMessageFilter::OnTCPCreatePrivate(int32 routing_id,
- uint32 plugin_dispatcher_id,
- uint32* socket_id) {
- CreateTCPSocket(routing_id, plugin_dispatcher_id, true, socket_id);
-}
-
-void PepperMessageFilter::OnTCPConnect(int32 routing_id,
- uint32 socket_id,
- const std::string& host,
- uint16_t port) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id);
- if (iter == tcp_sockets_.end()) {
- NOTREACHED();
- return;
- }
-
- // This is only supported by PPB_TCPSocket_Private.
- if (!iter->second->private_api()) {
- NOTREACHED();
- return;
- }
-
- content::SocketPermissionRequest params(
- content::SocketPermissionRequest::TCP_CONNECT, host, port);
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&PepperMessageFilter::CanUseSocketAPIs, this,
- routing_id, params, true /* private_api */),
- base::Bind(&PepperMessageFilter::DoTCPConnect, this,
- routing_id, socket_id, host, port));
-}
-
-void PepperMessageFilter::DoTCPConnect(int32 routing_id,
- uint32 socket_id,
- const std::string& host,
- uint16_t port,
- bool allowed) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id);
- if (iter == tcp_sockets_.end()) {
- // Due to current permission check process (IO -> UI -> IO) some
- // calls to the TCP socket interface can be intermixed (like
- // Connect and Close). So, NOTREACHED() is not appropriate here.
- return;
- }
-
- if (routing_id == iter->second->routing_id() && allowed)
- iter->second->Connect(host, port);
- else
- iter->second->SendConnectACKError(PP_ERROR_NOACCESS);
-}
-
-void PepperMessageFilter::OnTCPConnectWithNetAddress(
- int32 routing_id,
- uint32 socket_id,
- const PP_NetAddress_Private& net_addr) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id);
- if (iter == tcp_sockets_.end()) {
- NOTREACHED();
- return;
- }
-
- content::SocketPermissionRequest params =
- pepper_socket_utils::CreateSocketPermissionRequest(
- content::SocketPermissionRequest::TCP_CONNECT, net_addr);
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&PepperMessageFilter::CanUseSocketAPIs, this,
- routing_id, params, iter->second->private_api()),
- base::Bind(&PepperMessageFilter::DoTCPConnectWithNetAddress, this,
- routing_id, socket_id, net_addr));
-}
-
-void PepperMessageFilter::DoTCPConnectWithNetAddress(
- int32 routing_id,
- uint32 socket_id,
- const PP_NetAddress_Private& net_addr,
- bool allowed) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id);
- if (iter == tcp_sockets_.end()) {
- // Due to current permission check process (IO -> UI -> IO) some
- // calls to the TCP socket interface can be intermixed (like
- // ConnectWithNetAddress and Close). So, NOTREACHED() is not
- // appropriate here.
- return;
- }
-
- if (routing_id == iter->second->routing_id() && allowed)
- iter->second->ConnectWithNetAddress(net_addr);
- else
- iter->second->SendConnectACKError(PP_ERROR_NOACCESS);
-}
-
-void PepperMessageFilter::OnTCPSSLHandshake(
- uint32 socket_id,
- const std::string& server_name,
- uint16_t server_port,
- const std::vector<std::vector<char> >& trusted_certs,
- const std::vector<std::vector<char> >& untrusted_certs) {
- TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id);
- if (iter == tcp_sockets_.end()) {
- NOTREACHED();
- return;
- }
-
- // This is only supported by PPB_TCPSocket_Private.
- if (!iter->second->private_api()) {
- NOTREACHED();
- return;
- }
-
- iter->second->SSLHandshake(server_name, server_port, trusted_certs,
- untrusted_certs);
-}
-
-void PepperMessageFilter::OnTCPRead(uint32 socket_id, int32_t bytes_to_read) {
- TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id);
- if (iter == tcp_sockets_.end()) {
- NOTREACHED();
- return;
- }
-
- iter->second->Read(bytes_to_read);
-}
-
-void PepperMessageFilter::OnTCPWrite(uint32 socket_id,
- const std::string& data) {
- TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id);
- if (iter == tcp_sockets_.end()) {
- NOTREACHED();
- return;
- }
-
- iter->second->Write(data);
-}
-
-void PepperMessageFilter::OnTCPDisconnect(uint32 socket_id) {
- TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id);
- if (iter == tcp_sockets_.end()) {
- NOTREACHED();
- return;
- }
-
- // Destroying the TCPSocket instance will cancel any pending completion
- // callback. From this point on, there won't be any messages associated with
- // this socket sent to the plugin side.
- tcp_sockets_.erase(iter);
-}
-
-void PepperMessageFilter::OnTCPSetOption(uint32 socket_id,
- PP_TCPSocket_Option name,
- const ppapi::SocketOptionData& value) {
- TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id);
- if (iter == tcp_sockets_.end()) {
- NOTREACHED();
- return;
- }
-
- iter->second->SetOption(name, value);
-}
-
-void PepperMessageFilter::OnNetworkMonitorStart(uint32 plugin_dispatcher_id) {
- // Support all in-process plugins, and ones with "private" permissions.
- if (plugin_type_ != PLUGIN_TYPE_IN_PROCESS &&
- !permissions_.HasPermission(ppapi::PERMISSION_PRIVATE)) {
- return;
- }
-
- if (network_monitor_ids_.empty())
- net::NetworkChangeNotifier::AddIPAddressObserver(this);
-
- network_monitor_ids_.insert(plugin_dispatcher_id);
- GetAndSendNetworkList();
-}
-
-void PepperMessageFilter::OnNetworkMonitorStop(uint32 plugin_dispatcher_id) {
- // Support all in-process plugins, and ones with "private" permissions.
- if (plugin_type_ != PLUGIN_TYPE_IN_PROCESS &&
- !permissions_.HasPermission(ppapi::PERMISSION_PRIVATE)) {
- return;
- }
-
- network_monitor_ids_.erase(plugin_dispatcher_id);
- if (network_monitor_ids_.empty())
- net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
-}
-
void PepperMessageFilter::OnX509CertificateParseDER(
const std::vector<char>& der,
bool* succeeded,
ppapi::PPB_X509Certificate_Fields* result) {
if (der.size() == 0)
*succeeded = false;
- *succeeded = PepperTCPSocket::GetCertificateFields(&der[0], der.size(),
- result);
-}
-
-uint32 PepperMessageFilter::GenerateSocketID() {
- // TODO(yzshen): Change to use Pepper resource ID as socket ID.
- //
- // Generate a socket ID. For each process which sends us socket requests, IDs
- // of living sockets must be unique, to each socket type.
- //
- // However, it is safe to generate IDs based on the internal state of a single
- // PepperSocketMessageHandler object, because for each plugin or renderer
- // process, there is at most one PepperMessageFilter (in other words, at most
- // one PepperSocketMessageHandler) talking to it.
- if (tcp_sockets_.size() >= kMaxSocketsAllowed)
- return kInvalidSocketID;
-
- uint32 socket_id = kInvalidSocketID;
- do {
- // Although it is unlikely, make sure that we won't cause any trouble when
- // the counter overflows.
- socket_id = next_socket_id_++;
- } while (socket_id == kInvalidSocketID ||
- tcp_sockets_.find(socket_id) != tcp_sockets_.end());
-
- return socket_id;
-}
-
-bool PepperMessageFilter::CanUseSocketAPIs(
- int32 render_id,
- const content::SocketPermissionRequest& params,
- bool private_api) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- // External plugins always get their own PepperMessageFilter, initialized with
- // a render view id. Use this instead of the one that came with the message,
- // which is actually an API ID.
- bool external_plugin = false;
- if (plugin_type_ == PLUGIN_TYPE_EXTERNAL_PLUGIN) {
- external_plugin = true;
- render_id = external_plugin_render_view_id_;
- }
-
- RenderViewHostImpl* render_view_host =
- RenderViewHostImpl::FromID(process_id_, render_id);
-
- return pepper_socket_utils::CanUseSocketAPIs(external_plugin,
- private_api,
- params,
- render_view_host);
-}
-
-void PepperMessageFilter::GetAndSendNetworkList() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- BrowserThread::PostBlockingPoolTask(
- FROM_HERE, base::Bind(&PepperMessageFilter::DoGetNetworkList, this));
-}
-
-void PepperMessageFilter::DoGetNetworkList() {
- scoped_ptr<net::NetworkInterfaceList> list(new net::NetworkInterfaceList());
- net::GetNetworkList(list.get());
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&PepperMessageFilter::SendNetworkList,
- this, base::Passed(&list)));
-}
-
-void PepperMessageFilter::SendNetworkList(
- scoped_ptr<net::NetworkInterfaceList> list) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- scoped_ptr< ::ppapi::NetworkList> list_copy(
- new ::ppapi::NetworkList(list->size()));
- for (size_t i = 0; i < list->size(); ++i) {
- const net::NetworkInterface& network = list->at(i);
- ::ppapi::NetworkInfo& network_copy = list_copy->at(i);
- network_copy.name = network.name;
-
- network_copy.addresses.resize(1, NetAddressPrivateImpl::kInvalidNetAddress);
- bool result = NetAddressPrivateImpl::IPEndPointToNetAddress(
- network.address, 0, &(network_copy.addresses[0]));
- DCHECK(result);
-
- // TODO(sergeyu): Currently net::NetworkInterfaceList provides
- // only name and one IP address. Add all other fields and copy
- // them here.
- network_copy.type = PP_NETWORKLIST_UNKNOWN;
- network_copy.state = PP_NETWORKLIST_UP;
- network_copy.display_name = network.name;
- network_copy.mtu = 0;
- }
- for (NetworkMonitorIdSet::iterator it = network_monitor_ids_.begin();
- it != network_monitor_ids_.end(); ++it) {
- Send(new PpapiMsg_PPBNetworkMonitor_NetworkList(
- ppapi::API_ID_PPB_NETWORKMANAGER_PRIVATE, *it, *list_copy));
- }
-}
-
-void PepperMessageFilter::CreateTCPSocket(int32 routing_id,
- uint32 plugin_dispatcher_id,
- bool private_api,
- uint32* socket_id) {
- *socket_id = GenerateSocketID();
- if (*socket_id == kInvalidSocketID)
- return;
-
- tcp_sockets_[*socket_id] = linked_ptr<PepperTCPSocket>(
- new PepperTCPSocket(this, routing_id, plugin_dispatcher_id, *socket_id,
- private_api));
+ *succeeded =
+ pepper_socket_utils::GetCertificateFields(&der[0], der.size(), result);
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_message_filter.h b/chromium/content/browser/renderer_host/pepper/pepper_message_filter.h
index 11c8fbd4902..3f5010ed40e 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_message_filter.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_message_filter.h
@@ -5,223 +5,35 @@
#ifndef CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_MESSAGE_FILTER_H_
#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_MESSAGE_FILTER_H_
-#include <map>
-#include <string>
#include <vector>
#include "base/basictypes.h"
#include "base/compiler_specific.h"
-#include "base/files/file_path.h"
-#include "base/memory/linked_ptr.h"
#include "base/memory/scoped_ptr.h"
-#include "base/process/process.h"
#include "content/public/browser/browser_message_filter.h"
-#include "content/public/browser/content_browser_client.h"
-#include "content/public/common/process_type.h"
-#include "net/base/net_util.h"
-#include "net/base/network_change_notifier.h"
-#include "net/http/transport_security_state.h"
-#include "net/socket/stream_socket.h"
-#include "net/ssl/ssl_config_service.h"
-#include "ppapi/c/pp_resource.h"
-#include "ppapi/c/pp_stdint.h"
-#include "ppapi/c/ppb_tcp_socket.h"
-#include "ppapi/c/private/ppb_flash.h"
-#include "ppapi/host/ppapi_host.h"
-#include "ppapi/shared_impl/ppapi_permissions.h"
-
-struct PP_NetAddress_Private;
-
-namespace base {
-class ListValue;
-}
-
-namespace net {
-class CertVerifier;
-class HostResolver;
-}
namespace ppapi {
class PPB_X509Certificate_Fields;
-class SocketOptionData;
}
namespace content {
-class BrowserContext;
-class PepperTCPSocket;
-class ResourceContext;
-// This class is used in two contexts, both supporting PPAPI plugins. The first
-// is on the renderer->browser channel, to handle requests from in-process
-// PPAPI plugins and any requests that the PPAPI implementation code in the
-// renderer needs to make. The second is on the plugin->browser channel to
-// handle requests that out-of-process plugins send directly to the browser.
-class PepperMessageFilter
- : public BrowserMessageFilter,
- public net::NetworkChangeNotifier::IPAddressObserver {
+// Message filter that handles IPC for PPB_X509Certificate_Private.
+class PepperMessageFilter : public BrowserMessageFilter {
public:
- // Constructor when used in the context of a render process.
- PepperMessageFilter(int process_id,
- BrowserContext* browser_context);
-
- // Constructor when used in the context of a PPAPI process..
- PepperMessageFilter(const ppapi::PpapiPermissions& permissions,
- net::HostResolver* host_resolver);
-
- // Constructor when used in the context of an external plugin, i.e. created by
- // the embedder using BrowserPpapiHost::CreateExternalPluginProcess.
- PepperMessageFilter(const ppapi::PpapiPermissions& permissions,
- net::HostResolver* host_resolver,
- int process_id,
- int render_view_id);
+ PepperMessageFilter();
// BrowserMessageFilter methods.
virtual bool OnMessageReceived(const IPC::Message& message,
bool* message_was_ok) OVERRIDE;
- // net::NetworkChangeNotifier::IPAddressObserver interface.
- virtual void OnIPAddressChanged() OVERRIDE;
-
- // Returns the host resolver (it may come from the resource context or the
- // host_resolver_ member).
- net::HostResolver* GetHostResolver();
-
- net::CertVerifier* GetCertVerifier();
- net::TransportSecurityState* GetTransportSecurityState();
-
- // Adds already accepted socket to the internal TCP sockets table. Takes
- // ownership over |socket|. In the case of failure (full socket table)
- // returns 0 and deletes |socket|. Otherwise, returns generated ID for
- // |socket|.
- uint32 AddAcceptedTCPSocket(int32 routing_id,
- uint32 plugin_dispatcher_id,
- net::StreamSocket* socket);
-
- const net::SSLConfig& ssl_config() { return ssl_config_; }
-
protected:
virtual ~PepperMessageFilter();
private:
- struct OnConnectTcpBoundInfo {
- int routing_id;
- int request_id;
- };
-
- // Containers for sockets keyed by socked_id.
- typedef std::map<uint32, linked_ptr<PepperTCPSocket> > TCPSocketMap;
-
- // Set of disptachers ID's that have subscribed for NetworkMonitor
- // notifications.
- typedef std::set<uint32> NetworkMonitorIdSet;
-
- void OnGetLocalTimeZoneOffset(base::Time t, double* result);
-
- void OnTCPCreate(int32 routing_id,
- uint32 plugin_dispatcher_id,
- uint32* socket_id);
- void OnTCPCreatePrivate(int32 routing_id,
- uint32 plugin_dispatcher_id,
- uint32* socket_id);
- void OnTCPConnect(int32 routing_id,
- uint32 socket_id,
- const std::string& host,
- uint16_t port);
- void OnTCPConnectWithNetAddress(int32 routing_id,
- uint32 socket_id,
- const PP_NetAddress_Private& net_addr);
- void OnTCPSSLHandshake(
- uint32 socket_id,
- const std::string& server_name,
- uint16_t server_port,
- const std::vector<std::vector<char> >& trusted_certs,
- const std::vector<std::vector<char> >& untrusted_certs);
- void OnTCPRead(uint32 socket_id, int32_t bytes_to_read);
- void OnTCPWrite(uint32 socket_id, const std::string& data);
- void OnTCPDisconnect(uint32 socket_id);
- void OnTCPSetOption(uint32 socket_id,
- PP_TCPSocket_Option name,
- const ppapi::SocketOptionData& value);
-
- void OnNetworkMonitorStart(uint32 plugin_dispatcher_id);
- void OnNetworkMonitorStop(uint32 plugin_dispatcher_id);
-
- void DoTCPConnect(int32 routing_id,
- uint32 socket_id,
- const std::string& host,
- uint16_t port,
- bool allowed);
- void DoTCPConnectWithNetAddress(int32 routing_id,
- uint32 socket_id,
- const PP_NetAddress_Private& net_addr,
- bool allowed);
void OnX509CertificateParseDER(const std::vector<char>& der,
bool* succeeded,
ppapi::PPB_X509Certificate_Fields* result);
- void OnUpdateActivity();
-
- uint32 GenerateSocketID();
-
- // Return true if render with given ID can use socket APIs.
- bool CanUseSocketAPIs(int32 render_id,
- const content::SocketPermissionRequest& params,
- bool private_api);
-
- void GetAndSendNetworkList();
- void DoGetNetworkList();
- void SendNetworkList(scoped_ptr<net::NetworkInterfaceList> list);
- void CreateTCPSocket(int32 routing_id,
- uint32 plugin_dispatcher_id,
- bool private_api,
- uint32* socket_id);
- enum PluginType {
- PLUGIN_TYPE_IN_PROCESS,
- PLUGIN_TYPE_OUT_OF_PROCESS,
- // External plugin means it was created through
- // BrowserPpapiHost::CreateExternalPluginProcess.
- PLUGIN_TYPE_EXTERNAL_PLUGIN,
- };
-
- PluginType plugin_type_;
-
- // When attached to an out-of-process plugin (be it native or NaCl) this
- // will have the Pepper permissions for the plugin. When attached to the
- // renderer channel, this will have no permissions listed (since there may
- // be many plugins sharing this channel).
- ppapi::PpapiPermissions permissions_;
-
- // Render process ID.
- int process_id_;
-
- // External plugin RenderView id to determine private API access. Normally, we
- // handle messages coming from multiple RenderViews, but external plugins
- // always creates a new PepperMessageFilter for each RenderView.
- int external_plugin_render_view_id_;
-
- // When non-NULL, this should be used instead of the host_resolver_.
- ResourceContext* const resource_context_;
-
- // When non-NULL, this should be used instead of the resource_context_. Use
- // GetHostResolver instead of accessing directly.
- net::HostResolver* host_resolver_;
-
- // The default SSL configuration settings are used, as opposed to Chrome's SSL
- // settings.
- net::SSLConfig ssl_config_;
- // This is lazily created. Users should use GetCertVerifier to retrieve it.
- scoped_ptr<net::CertVerifier> cert_verifier_;
- // This is lazily created. Users should use GetTransportSecurityState to
- // retrieve it.
- scoped_ptr<net::TransportSecurityState> transport_security_state_;
-
- uint32 next_socket_id_;
-
- TCPSocketMap tcp_sockets_;
-
- NetworkMonitorIdSet network_monitor_ids_;
-
- base::FilePath browser_path_;
- bool incognito_;
DISALLOW_COPY_AND_ASSIGN(PepperMessageFilter);
};
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.cc
new file mode 100644
index 00000000000..b53a60b779b
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.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 "content/browser/renderer_host/pepper/pepper_network_monitor_host.h"
+
+#include "base/task_runner_util.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
+#include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/common/socket_permission_request.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/private/net_address_private_impl.h"
+
+
+namespace content {
+
+namespace {
+
+bool CanUseNetworkMonitor(bool external_plugin,
+ int render_process_id,
+ int render_view_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ SocketPermissionRequest request = SocketPermissionRequest(
+ SocketPermissionRequest::NETWORK_STATE, std::string(), 0);
+ return pepper_socket_utils::CanUseSocketAPIs(
+ external_plugin, false /* private_api */, &request, render_process_id,
+ render_view_id);
+}
+
+scoped_ptr<net::NetworkInterfaceList> GetNetworkList() {
+ scoped_ptr<net::NetworkInterfaceList> list(new net::NetworkInterfaceList());
+ net::GetNetworkList(list.get());
+ return list.Pass();
+}
+
+} // namespace
+
+PepperNetworkMonitorHost::PepperNetworkMonitorHost(
+ BrowserPpapiHostImpl* host,
+ PP_Instance instance,
+ PP_Resource resource)
+ : ResourceHost(host->GetPpapiHost(), instance, resource),
+ weak_factory_(this) {
+ int render_process_id;
+ int render_view_id;
+ host->GetRenderViewIDsForInstance(instance,
+ &render_process_id,
+ &render_view_id);
+
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&CanUseNetworkMonitor, host->external_plugin(),
+ render_process_id, render_view_id),
+ base::Bind(&PepperNetworkMonitorHost::OnPermissionCheckResult,
+ weak_factory_.GetWeakPtr()));
+}
+
+PepperNetworkMonitorHost::~PepperNetworkMonitorHost() {
+ net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
+}
+
+void PepperNetworkMonitorHost::OnIPAddressChanged() {
+ GetAndSendNetworkList();
+}
+
+void PepperNetworkMonitorHost::OnPermissionCheckResult(
+ bool can_use_network_monitor) {
+ if (!can_use_network_monitor) {
+ host()->SendUnsolicitedReply(pp_resource(),
+ PpapiPluginMsg_NetworkMonitor_Forbidden());
+ return;
+ }
+
+ net::NetworkChangeNotifier::AddIPAddressObserver(this);
+ GetAndSendNetworkList();
+}
+
+void PepperNetworkMonitorHost::GetAndSendNetworkList() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ // Call GetNetworkList() on a thread that allows blocking IO.
+ base::PostTaskAndReplyWithResult(
+ BrowserThread::GetBlockingPool(), FROM_HERE,
+ base::Bind(&GetNetworkList),
+ base::Bind(&PepperNetworkMonitorHost::SendNetworkList,
+ weak_factory_.GetWeakPtr()));
+}
+
+void PepperNetworkMonitorHost::SendNetworkList(
+ scoped_ptr<net::NetworkInterfaceList> list) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ scoped_ptr<ppapi::proxy::SerializedNetworkList> list_copy(
+ new ppapi::proxy::SerializedNetworkList(list->size()));
+ for (size_t i = 0; i < list->size(); ++i) {
+ const net::NetworkInterface& network = list->at(i);
+ ppapi::proxy::SerializedNetworkInfo& network_copy = list_copy->at(i);
+ network_copy.name = network.name;
+
+ network_copy.addresses.resize(
+ 1, ppapi::NetAddressPrivateImpl::kInvalidNetAddress);
+ bool result = ppapi::NetAddressPrivateImpl::IPEndPointToNetAddress(
+ network.address, 0, &(network_copy.addresses[0]));
+ DCHECK(result);
+
+ // TODO(sergeyu): Currently net::NetworkInterfaceList provides
+ // only name and one IP address. Add all other fields and copy
+ // them here.
+ network_copy.type = PP_NETWORKLIST_TYPE_UNKNOWN;
+ network_copy.state = PP_NETWORKLIST_STATE_UP;
+ network_copy.display_name = network.name;
+ network_copy.mtu = 0;
+ }
+ host()->SendUnsolicitedReply(
+ pp_resource(), PpapiPluginMsg_NetworkMonitor_NetworkList(*list_copy));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.h b/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.h
new file mode 100644
index 00000000000..e27f8a2ac21
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.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_PEPPER_PEPPER_NETWORK_MONITOR_HOST_H_
+#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_NETWORK_MONITOR_HOST_H_
+
+#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
+#include "content/common/content_export.h"
+#include "net/base/net_util.h"
+#include "net/base/network_change_notifier.h"
+#include "ppapi/host/host_message_context.h"
+#include "ppapi/host/resource_host.h"
+
+namespace content {
+
+class BrowserPpapiHostImpl;
+
+// The host for PPB_NetworkMonitor. This class lives on the IO thread.
+class CONTENT_EXPORT PepperNetworkMonitorHost
+ : public ppapi::host::ResourceHost,
+ public net::NetworkChangeNotifier::IPAddressObserver {
+ public:
+ PepperNetworkMonitorHost(
+ BrowserPpapiHostImpl* host,
+ PP_Instance instance,
+ PP_Resource resource);
+
+ virtual ~PepperNetworkMonitorHost();
+
+ // net::NetworkChangeNotifier::IPAddressObserver interface.
+ virtual void OnIPAddressChanged() OVERRIDE;
+
+ private:
+ void OnPermissionCheckResult(bool can_use_network_monitor);
+
+ void GetAndSendNetworkList();
+ void SendNetworkList(scoped_ptr<net::NetworkInterfaceList> list);
+
+ ppapi::host::ReplyMessageContext reply_context_;
+
+ base::WeakPtrFactory<PepperNetworkMonitorHost> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperNetworkMonitorHost);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_NETWORK_MONITOR_HOST_H_
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc
index 6042badfc92..13f0fc3733f 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc
@@ -84,7 +84,7 @@ PepperNetworkProxyHost::GetUIThreadDataOnUIThread(int render_process_id,
result.is_allowed = pepper_socket_utils::CanUseSocketAPIs(
is_external_plugin,
false /* is_private_api */,
- request,
+ &request,
render_view_host);
}
return result;
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 a5b95ceb223..e4c8aa71dc1 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.cc
@@ -16,6 +16,7 @@
#include "ppapi/host/resource_host.h"
#include "ppapi/proxy/ppapi_message_utils.h"
#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppapi_message_utils.h"
#include "ppapi/proxy/resource_message_params.h"
namespace content {
@@ -28,8 +29,7 @@ PepperRendererConnection::PepperRendererConnection(int render_process_id)
"",
base::FilePath(),
base::FilePath(),
- false,
- NULL));
+ false));
}
PepperRendererConnection::~PepperRendererConnection() {
@@ -72,10 +72,8 @@ bool PepperRendererConnection::OnMessageReceived(const IPC::Message& msg,
bool handled = true;
IPC_BEGIN_MESSAGE_MAP_EX(PepperRendererConnection, msg, *message_was_ok)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_CreateResourceHostFromHost,
- OnMsgCreateResourceHostFromHost)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_FileRef_GetInfoForRenderer,
- OnMsgFileRefGetInfoForRenderer)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_CreateResourceHostsFromHost,
+ OnMsgCreateResourceHostsFromHost)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidCreateInProcessInstance,
OnMsgDidCreateInProcessInstance)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidDeleteInProcessInstance,
@@ -86,79 +84,48 @@ bool PepperRendererConnection::OnMessageReceived(const IPC::Message& msg,
return handled;
}
-void PepperRendererConnection::OnMsgCreateResourceHostFromHost(
+void PepperRendererConnection::OnMsgCreateResourceHostsFromHost(
int routing_id,
int child_process_id,
const ppapi::proxy::ResourceMessageCallParams& params,
PP_Instance instance,
- const IPC::Message& nested_msg) {
+ const std::vector<IPC::Message>& nested_msgs) {
BrowserPpapiHostImpl* host = GetHostForChildProcess(child_process_id);
- int pending_resource_host_id;
+ std::vector<int> pending_resource_host_ids(nested_msgs.size(), 0);
if (!host) {
DLOG(ERROR) << "Invalid plugin process ID.";
- pending_resource_host_id = 0;
} else {
- // 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_msg.type() == PpapiHostMsg_FileRef_CreateExternal::ID) {
- 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));
+ 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));
+ }
}
}
- }
-
- if (!resource_host.get()) {
- resource_host = host->GetPpapiHost()->CreateResourceHost(params,
- instance,
- nested_msg);
- }
- pending_resource_host_id =
- host->GetPpapiHost()->AddPendingResourceHost(resource_host.Pass());
- }
-
- Send(new PpapiHostMsg_CreateResourceHostFromHostReply(
- routing_id, params.sequence(), pending_resource_host_id));
-}
-void PepperRendererConnection::OnMsgFileRefGetInfoForRenderer(
- int routing_id,
- int child_process_id,
- int32_t sequence,
- const std::vector<PP_Resource>& resources) {
- std::vector<PP_Resource> out_resources;
- std::vector<PP_FileSystemType> fs_types;
- std::vector<std::string> file_system_url_specs;
- std::vector<base::FilePath> external_paths;
+ if (!resource_host.get()) {
+ resource_host = host->GetPpapiHost()->CreateResourceHost(
+ params, instance, nested_msgs[i]);
+ }
- BrowserPpapiHostImpl* host = GetHostForChildProcess(child_process_id);
- if (host) {
- for (size_t i = 0; i < resources.size(); ++i) {
- ppapi::host::ResourceHost* resource_host =
- host->GetPpapiHost()->GetResourceHost(resources[i]);
- if (resource_host && resource_host->IsFileRefHost()) {
- PepperFileRefHost* file_ref_host =
- static_cast<PepperFileRefHost*>(resource_host);
- out_resources.push_back(resources[i]);
- fs_types.push_back(file_ref_host->GetFileSystemType());
- file_system_url_specs.push_back(file_ref_host->GetFileSystemURLSpec());
- external_paths.push_back(file_ref_host->GetExternalPath());
+ if (resource_host.get()) {
+ pending_resource_host_ids[i] =
+ host->GetPpapiHost()->AddPendingResourceHost(resource_host.Pass());
}
}
}
- Send(new PpapiHostMsg_FileRef_GetInfoForRendererReply(
- routing_id,
- sequence,
- out_resources,
- fs_types,
- file_system_url_specs,
- external_paths));
+
+ Send(new PpapiHostMsg_CreateResourceHostsFromHostReply(
+ routing_id, params.sequence(), pending_resource_host_ids));
}
void PepperRendererConnection::OnMsgDidCreateInProcessInstance(
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.h b/chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.h
index 43923465d0b..157827a9cfd 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_RENDERER_CONNECTION_H_
#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_RENDERER_CONNECTION_H_
+#include <vector>
+
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
@@ -45,18 +47,12 @@ class PepperRendererConnection : public BrowserMessageFilter {
// PepperRendererConnection, which serves as the host for in-process plugins.
BrowserPpapiHostImpl* GetHostForChildProcess(int child_process_id) const;
- void OnMsgCreateResourceHostFromHost(
+ void OnMsgCreateResourceHostsFromHost(
int routing_id,
int child_process_id,
const ppapi::proxy::ResourceMessageCallParams& params,
PP_Instance instance,
- const IPC::Message& nested_msg);
-
- void OnMsgFileRefGetInfoForRenderer(
- int routing_id,
- int child_process_id,
- int32_t sequence_num,
- const std::vector<PP_Resource>& resources);
+ const std::vector<IPC::Message>& nested_msgs);
void OnMsgDidCreateInProcessInstance(
PP_Instance instance,
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 5402823f01e..5816ce4831f 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_security_helper.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_security_helper.cc
@@ -10,8 +10,18 @@
namespace content {
-bool CanOpenWithPepperFlags(int pp_open_flags, int child_id,
- const base::FilePath& file) {
+namespace {
+
+template <typename CanRead, typename CanWrite,
+ typename CanCreate, typename CanCreateWrite,
+ typename FileID>
+bool CanOpenFileWithPepperFlags(CanRead can_read,
+ CanWrite can_write,
+ CanCreate can_create,
+ CanCreateWrite can_create_write,
+ int pp_open_flags,
+ int child_id,
+ const FileID& file) {
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
@@ -22,33 +32,53 @@ bool CanOpenWithPepperFlags(int pp_open_flags, int child_id,
bool pp_exclusive = !!(pp_open_flags & PP_FILEOPENFLAG_EXCLUSIVE);
bool pp_append = !!(pp_open_flags & PP_FILEOPENFLAG_APPEND);
- if (pp_read && !policy->CanReadFile(child_id, file))
+ if (pp_read && !(policy->*can_read)(child_id, file))
return false;
- if (pp_write && !policy->CanWriteFile(child_id, file))
+ if (pp_write && !(policy->*can_write)(child_id, file))
return false;
- if (pp_append) {
- // Given ChildSecurityPolicyImpl's current definition of permissions,
- // APPEND is never supported.
+ // TODO(tommycli): Maybe tighten up required permission. crbug.com/284792
+ if (pp_append && !(policy->*can_create_write)(child_id, file))
return false;
- }
if (pp_truncate && !pp_write)
return false;
if (pp_create) {
if (pp_exclusive) {
- return policy->CanCreateFile(child_id, file);
+ return (policy->*can_create)(child_id, file);
} else {
// Asks for too much, but this is the only grant that allows overwrite.
- return policy->CanCreateWriteFile(child_id, file);
+ return (policy->*can_create_write)(child_id, file);
}
} else if (pp_truncate) {
- return policy->CanCreateWriteFile(child_id, file);
+ return (policy->*can_create_write)(child_id, file);
}
return true;
}
+}
+
+bool CanOpenWithPepperFlags(int pp_open_flags, int child_id,
+ const base::FilePath& file) {
+ return CanOpenFileWithPepperFlags(
+ &ChildProcessSecurityPolicyImpl::CanReadFile,
+ &ChildProcessSecurityPolicyImpl::CanWriteFile,
+ &ChildProcessSecurityPolicyImpl::CanCreateFile,
+ &ChildProcessSecurityPolicyImpl::CanCreateWriteFile,
+ pp_open_flags, child_id, file);
+}
+
+bool CanOpenFileSystemURLWithPepperFlags(int pp_open_flags, int child_id,
+ const fileapi::FileSystemURL& url) {
+ return CanOpenFileWithPepperFlags(
+ &ChildProcessSecurityPolicyImpl::CanReadFileSystemFile,
+ &ChildProcessSecurityPolicyImpl::CanWriteFileSystemFile,
+ &ChildProcessSecurityPolicyImpl::CanCreateFileSystemFile,
+ &ChildProcessSecurityPolicyImpl::CanCreateWriteFileSystemFile,
+ pp_open_flags, child_id, url);
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_security_helper.h b/chromium/content/browser/renderer_host/pepper/pepper_security_helper.h
index 4a3cea5874a..d0a39831324 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_security_helper.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_security_helper.h
@@ -7,15 +7,23 @@
#include "base/files/file_path.h"
#include "content/common/content_export.h"
+#include "webkit/browser/fileapi/file_system_url.h"
namespace content {
-// Helper method that returns whether or not the child process is allowed to
+// Helper function that returns whether or not the child process is allowed to
// open the specified |file| with the specified |pp_open_flags|.
CONTENT_EXPORT bool CanOpenWithPepperFlags(int pp_open_flags,
int child_id,
const base::FilePath& file);
+// Helper function that returns whether or not the child process is allowed to
+// open the specified file system |url| with the specified |pp_open_flags|.
+CONTENT_EXPORT bool CanOpenFileSystemURLWithPepperFlags(
+ int pp_open_flags,
+ int child_id,
+ const fileapi::FileSystemURL& url);
+
} // namespace content
#endif // CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_SECURITY_HELPER_H_
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.cc b/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.cc
index 9dc585e3315..2f109cddb71 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.cc
@@ -8,13 +8,16 @@
#include <vector>
#include "base/logging.h"
+#include "base/memory/ref_counted.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/site_instance.h"
#include "content/public/common/content_client.h"
+#include "net/cert/x509_certificate.h"
#include "ppapi/c/private/ppb_net_address_private.h"
#include "ppapi/shared_impl/private/net_address_private_impl.h"
+#include "ppapi/shared_impl/private/ppb_x509_certificate_private_shared.h"
namespace content {
namespace pepper_socket_utils {
@@ -34,7 +37,7 @@ SocketPermissionRequest CreateSocketPermissionRequest(
bool CanUseSocketAPIs(bool external_plugin,
bool private_api,
- const SocketPermissionRequest& params,
+ const SocketPermissionRequest* params,
int render_process_id,
int render_view_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -48,7 +51,7 @@ bool CanUseSocketAPIs(bool external_plugin,
bool CanUseSocketAPIs(bool external_plugin,
bool private_api,
- const SocketPermissionRequest& params,
+ const SocketPermissionRequest* params,
RenderViewHost* render_view_host) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -77,5 +80,60 @@ bool CanUseSocketAPIs(bool external_plugin,
return true;
}
+bool GetCertificateFields(const net::X509Certificate& cert,
+ ppapi::PPB_X509Certificate_Fields* fields) {
+ const net::CertPrincipal& issuer = cert.issuer();
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_COMMON_NAME,
+ new base::StringValue(issuer.common_name));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_LOCALITY_NAME,
+ new base::StringValue(issuer.locality_name));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_STATE_OR_PROVINCE_NAME,
+ new base::StringValue(issuer.state_or_province_name));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_COUNTRY_NAME,
+ new base::StringValue(issuer.country_name));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_ORGANIZATION_NAME,
+ new base::StringValue(JoinString(issuer.organization_names, '\n')));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_ORGANIZATION_UNIT_NAME,
+ new base::StringValue(JoinString(issuer.organization_unit_names, '\n')));
+
+ const net::CertPrincipal& subject = cert.subject();
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_COMMON_NAME,
+ new base::StringValue(subject.common_name));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_LOCALITY_NAME,
+ new base::StringValue(subject.locality_name));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_STATE_OR_PROVINCE_NAME,
+ new base::StringValue(subject.state_or_province_name));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_COUNTRY_NAME,
+ new base::StringValue(subject.country_name));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_ORGANIZATION_NAME,
+ new base::StringValue(JoinString(subject.organization_names, '\n')));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_ORGANIZATION_UNIT_NAME,
+ new base::StringValue(JoinString(subject.organization_unit_names, '\n')));
+
+ const std::string& serial_number = cert.serial_number();
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_SERIAL_NUMBER,
+ base::BinaryValue::CreateWithCopiedBuffer(serial_number.data(),
+ serial_number.length()));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_VALIDITY_NOT_BEFORE,
+ new base::FundamentalValue(cert.valid_start().ToDoubleT()));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_VALIDITY_NOT_AFTER,
+ new base::FundamentalValue(cert.valid_expiry().ToDoubleT()));
+ std::string der;
+ net::X509Certificate::GetDEREncoded(cert.os_cert_handle(), &der);
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_RAW,
+ base::BinaryValue::CreateWithCopiedBuffer(der.data(), der.length()));
+ return true;
+}
+
+bool GetCertificateFields(const char* der,
+ uint32_t length,
+ ppapi::PPB_X509Certificate_Fields* fields) {
+ scoped_refptr<net::X509Certificate> cert =
+ net::X509Certificate::CreateFromBytes(der, length);
+ if (!cert.get())
+ return false;
+ return GetCertificateFields(*cert.get(), fields);
+}
+
} // namespace pepper_socket_utils
} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.h b/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.h
index 7a0cef56a5c..1a1a26cac19 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.h
@@ -6,9 +6,18 @@
#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_SOCKET_UTILS_H_
#include "content/public/common/socket_permission_request.h"
+#include "ppapi/c/pp_stdint.h"
struct PP_NetAddress_Private;
+namespace net {
+class X509Certificate;
+}
+
+namespace ppapi {
+class PPB_X509Certificate_Fields;
+}
+
namespace content {
class RenderViewHost;
@@ -19,18 +28,32 @@ SocketPermissionRequest CreateSocketPermissionRequest(
SocketPermissionRequest::OperationType type,
const PP_NetAddress_Private& net_addr);
+// Returns true if the socket operation specified by |params| is allowed.
+// If |params| is NULL, this method checks the basic "socket" permission, which
+// is for those operations that don't require a specific socket permission rule.
bool CanUseSocketAPIs(bool external_plugin,
bool private_api,
- const SocketPermissionRequest& params,
+ const SocketPermissionRequest* params,
int render_process_id,
int render_view_id);
// TODO (ygorshenin@): remove this method.
bool CanUseSocketAPIs(bool external_plugin,
bool private_api,
- const SocketPermissionRequest& params,
+ const SocketPermissionRequest* params,
RenderViewHost* render_view_host);
+// Extracts the certificate field data from a net::X509Certificate into
+// PPB_X509Certificate_Fields.
+bool GetCertificateFields(const net::X509Certificate& cert,
+ ppapi::PPB_X509Certificate_Fields* fields);
+
+// Extracts the certificate field data from the DER representation of a
+// certificate into PPB_X509Certificate_Fields.
+bool GetCertificateFields(const char* der,
+ uint32_t length,
+ ppapi::PPB_X509Certificate_Fields* fields);
+
} // namespace pepper_socket_utils
} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc b/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc
index 48c8291cab9..063c11ed784 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc
@@ -8,20 +8,22 @@
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
+#include "content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h"
#include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/socket_permission_request.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/base/net_util.h"
-#include "net/socket/tcp_client_socket.h"
-#include "net/socket/tcp_server_socket.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/private/ppb_net_address_private.h"
#include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/error_conversion.h"
+#include "ppapi/host/ppapi_host.h"
+#include "ppapi/host/resource_host.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/shared_impl/api_id.h"
+#include "ppapi/shared_impl/ppb_tcp_socket_shared.h"
#include "ppapi/shared_impl/private/net_address_private_impl.h"
using ppapi::NetAddressPrivateImpl;
@@ -36,18 +38,21 @@ size_t g_num_instances = 0;
namespace content {
PepperTCPServerSocketMessageFilter::PepperTCPServerSocketMessageFilter(
+ ContentBrowserPepperHostFactory* factory,
BrowserPpapiHostImpl* host,
PP_Instance instance,
- bool private_api,
- const scoped_refptr<PepperMessageFilter>& pepper_message_filter)
- : state_(STATE_BEFORE_LISTENING),
- pepper_message_filter_(pepper_message_filter),
+ bool private_api)
+ : ppapi_host_(host->GetPpapiHost()),
+ factory_(factory),
+ instance_(instance),
+ state_(STATE_BEFORE_LISTENING),
external_plugin_(host->external_plugin()),
private_api_(private_api),
render_process_id_(0),
render_view_id_(0) {
++g_num_instances;
- DCHECK(host);
+ DCHECK(factory_);
+ DCHECK(ppapi_host_);
if (!host->GetRenderViewIDsForInstance(instance,
&render_process_id_,
&render_view_id_)) {
@@ -83,7 +88,7 @@ int32_t PepperTCPServerSocketMessageFilter::OnResourceMessageReceived(
IPC_BEGIN_MESSAGE_MAP(PepperTCPServerSocketMessageFilter, msg)
PPAPI_DISPATCH_HOST_RESOURCE_CALL(
PpapiHostMsg_TCPServerSocket_Listen, OnMsgListen)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
PpapiHostMsg_TCPServerSocket_Accept, OnMsgAccept)
PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
PpapiHostMsg_TCPServerSocket_StopListening, OnMsgStopListening)
@@ -103,7 +108,7 @@ int32_t PepperTCPServerSocketMessageFilter::OnMsgListen(
content::SocketPermissionRequest::TCP_LISTEN, addr);
if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
private_api_,
- request,
+ &request,
render_process_id_,
render_view_id_)) {
return PP_ERROR_NOACCESS;
@@ -117,8 +122,7 @@ int32_t PepperTCPServerSocketMessageFilter::OnMsgListen(
}
int32_t PepperTCPServerSocketMessageFilter::OnMsgAccept(
- const ppapi::host::HostMessageContext* context,
- uint32 plugin_dispatcher_id) {
+ const ppapi::host::HostMessageContext* context) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(context);
@@ -129,12 +133,12 @@ int32_t PepperTCPServerSocketMessageFilter::OnMsgAccept(
ppapi::host::ReplyMessageContext reply_context(
context->MakeReplyMessageContext());
int net_result = socket_->Accept(
- &socket_buffer_,
+ &accepted_socket_,
+ &accepted_address_,
base::Bind(&PepperTCPServerSocketMessageFilter::OnAcceptCompleted,
- base::Unretained(this),
- reply_context, plugin_dispatcher_id));
+ base::Unretained(this), reply_context));
if (net_result != net::ERR_IO_PENDING)
- OnAcceptCompleted(reply_context, plugin_dispatcher_id, net_result);
+ OnAcceptCompleted(reply_context, net_result);
return PP_OK_COMPLETIONPENDING;
}
@@ -165,8 +169,22 @@ void PepperTCPServerSocketMessageFilter::DoListen(
state_ = STATE_LISTEN_IN_PROGRESS;
- socket_.reset(new net::TCPServerSocket(NULL, net::NetLog::Source()));
- int net_result = socket_->Listen(net::IPEndPoint(address, port), backlog);
+ socket_.reset(new net::TCPSocket(NULL, net::NetLog::Source()));
+ int net_result = net::OK;
+ do {
+ net::IPEndPoint ip_end_point(address, port);
+ net_result = socket_->Open(ip_end_point.GetFamily());
+ if (net_result != net::OK)
+ break;
+ net_result = socket_->SetDefaultOptionsForServer();
+ if (net_result != net::OK)
+ break;
+ net_result = socket_->Bind(ip_end_point);
+ if (net_result != net::OK)
+ break;
+ net_result = socket_->Listen(backlog);
+ } while (false);
+
if (net_result != net::ERR_IO_PENDING)
OnListenCompleted(context, net_result);
}
@@ -211,7 +229,6 @@ void PepperTCPServerSocketMessageFilter::OnListenCompleted(
void PepperTCPServerSocketMessageFilter::OnAcceptCompleted(
const ppapi::host::ReplyMessageContext& context,
- uint32 plugin_dispatcher_id,
int net_result) {
if (state_ != STATE_ACCEPT_IN_PROGRESS) {
SendAcceptError(context, PP_ERROR_FAILED);
@@ -226,16 +243,15 @@ void PepperTCPServerSocketMessageFilter::OnAcceptCompleted(
return;
}
- DCHECK(socket_buffer_.get());
+ DCHECK(accepted_socket_.get());
- scoped_ptr<net::StreamSocket> socket(socket_buffer_.release());
net::IPEndPoint ip_end_point_local;
- net::IPEndPoint ip_end_point_remote;
PP_NetAddress_Private local_addr = NetAddressPrivateImpl::kInvalidNetAddress;
PP_NetAddress_Private remote_addr = NetAddressPrivateImpl::kInvalidNetAddress;
int32_t pp_result =
- NetErrorToPepperError(socket->GetLocalAddress(&ip_end_point_local));
+ NetErrorToPepperError(accepted_socket_->GetLocalAddress(
+ &ip_end_point_local));
if (pp_result != PP_OK) {
SendAcceptError(context, pp_result);
return;
@@ -243,33 +259,27 @@ void PepperTCPServerSocketMessageFilter::OnAcceptCompleted(
if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
ip_end_point_local.address(),
ip_end_point_local.port(),
- &local_addr)) {
- SendAcceptError(context, PP_ERROR_FAILED);
- return;
- }
- pp_result =
- NetErrorToPepperError(socket->GetPeerAddress(&ip_end_point_remote));
- if (pp_result != PP_OK) {
- SendAcceptError(context, pp_result);
- return;
- }
- if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
- ip_end_point_remote.address(),
- ip_end_point_remote.port(),
+ &local_addr) ||
+ !NetAddressPrivateImpl::IPEndPointToNetAddress(
+ accepted_address_.address(),
+ accepted_address_.port(),
&remote_addr)) {
SendAcceptError(context, PP_ERROR_FAILED);
return;
}
- if (!pepper_message_filter_.get() || plugin_dispatcher_id == 0) {
- SendAcceptError(context, PP_ERROR_FAILED);
+
+ scoped_ptr<ppapi::host::ResourceHost> host =
+ factory_->CreateAcceptedTCPSocket(
+ instance_, ppapi::TCP_SOCKET_VERSION_PRIVATE,
+ accepted_socket_.Pass());
+ if (!host) {
+ SendAcceptError(context, PP_ERROR_NOSPACE);
return;
}
- uint32 accepted_socket_id = pepper_message_filter_->AddAcceptedTCPSocket(
- ppapi::API_ID_PPB_TCPSOCKET_PRIVATE,
- plugin_dispatcher_id,
- socket.release());
- if (accepted_socket_id != 0) {
- SendAcceptReply(context, PP_OK, accepted_socket_id, local_addr,
+ int pending_resource_id = ppapi_host_->AddPendingResourceHost(host.Pass());
+ if (pending_resource_id) {
+ SendAcceptReply(context, PP_OK, pending_resource_id,
+ local_addr,
remote_addr);
} else {
SendAcceptError(context, PP_ERROR_NOSPACE);
@@ -296,13 +306,13 @@ void PepperTCPServerSocketMessageFilter::SendListenError(
void PepperTCPServerSocketMessageFilter::SendAcceptReply(
const ppapi::host::ReplyMessageContext& context,
int32_t pp_result,
- uint32 accepted_socket_id,
+ int pending_resource_id,
const PP_NetAddress_Private& local_addr,
const PP_NetAddress_Private& remote_addr) {
ppapi::host::ReplyMessageContext reply_context(context);
reply_context.params.set_result(pp_result);
SendReply(reply_context, PpapiPluginMsg_TCPServerSocket_AcceptReply(
- accepted_socket_id, local_addr, remote_addr));
+ pending_resource_id, local_addr, remote_addr));
}
void PepperTCPServerSocketMessageFilter::SendAcceptError(
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h b/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h
index ad8cf19f287..5d17333c9e8 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h
@@ -9,30 +9,35 @@
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
-#include "content/browser/renderer_host/pepper/pepper_message_filter.h"
#include "content/common/content_export.h"
+#include "net/base/ip_endpoint.h"
+#include "net/socket/tcp_socket.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/host/resource_message_filter.h"
struct PP_NetAddress_Private;
-namespace net {
-class ServerSocket;
-class StreamSocket;
+namespace ppapi {
+namespace host {
+class PpapiHost;
+}
}
namespace content {
class BrowserPpapiHostImpl;
+class ContentBrowserPepperHostFactory;
+// TODO(yzshen): Remove this class entirely and let
+// TCPServerSocketPrivateResource inherit TCPSocketResourceBase.
class CONTENT_EXPORT PepperTCPServerSocketMessageFilter
: public ppapi::host::ResourceMessageFilter {
public:
PepperTCPServerSocketMessageFilter(
+ ContentBrowserPepperHostFactory* factory,
BrowserPpapiHostImpl* host,
PP_Instance instance,
- bool private_api,
- const scoped_refptr<PepperMessageFilter>& pepper_message_filter);
+ bool private_api);
static size_t GetNumInstances();
@@ -58,8 +63,7 @@ class CONTENT_EXPORT PepperTCPServerSocketMessageFilter
int32_t OnMsgListen(const ppapi::host::HostMessageContext* context,
const PP_NetAddress_Private& addr,
int32_t backlog);
- int32_t OnMsgAccept(const ppapi::host::HostMessageContext* context,
- uint32 plugin_dispatcher_id);
+ int32_t OnMsgAccept(const ppapi::host::HostMessageContext* context);
int32_t OnMsgStopListening(const ppapi::host::HostMessageContext* context);
void DoListen(const ppapi::host::ReplyMessageContext& context,
@@ -69,7 +73,6 @@ class CONTENT_EXPORT PepperTCPServerSocketMessageFilter
void OnListenCompleted(const ppapi::host::ReplyMessageContext& context,
int net_result);
void OnAcceptCompleted(const ppapi::host::ReplyMessageContext& context,
- uint32 plugin_dispatcher_id,
int net_result);
void SendListenReply(const ppapi::host::ReplyMessageContext& context,
@@ -79,17 +82,23 @@ class CONTENT_EXPORT PepperTCPServerSocketMessageFilter
int32_t pp_result);
void SendAcceptReply(const ppapi::host::ReplyMessageContext& context,
int32_t pp_result,
- uint32 accepted_socket_id,
+ int pending_resource_id,
const PP_NetAddress_Private& local_addr,
const PP_NetAddress_Private& remote_addr);
void SendAcceptError(const ppapi::host::ReplyMessageContext& context,
int32_t pp_result);
// Following fields are initialized and used only on the IO thread.
+ // Non-owning ptr.
+ ppapi::host::PpapiHost* ppapi_host_;
+ // Non-owning ptr.
+ ContentBrowserPepperHostFactory* factory_;
+ PP_Instance instance_;
+
State state_;
- scoped_ptr<net::ServerSocket> socket_;
- scoped_ptr<net::StreamSocket> socket_buffer_;
- scoped_refptr<PepperMessageFilter> pepper_message_filter_;
+ scoped_ptr<net::TCPSocket> socket_;
+ scoped_ptr<net::TCPSocket> accepted_socket_;
+ net::IPEndPoint accepted_address_;
// Following fields are initialized on the IO thread but used only
// on the UI thread.
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket.cc b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket.cc
index f05be8783ed..c5b752aa7f5 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket.cc
@@ -87,10 +87,12 @@ void PepperTCPSocket::Connect(const std::string& host, uint16_t port) {
connection_state_ = CONNECT_IN_PROGRESS;
net::HostResolver::RequestInfo request_info(net::HostPortPair(host, port));
- resolver_.reset(new net::SingleRequestHostResolver(
- manager_->GetHostResolver()));
+ resolver_.reset(
+ new net::SingleRequestHostResolver(manager_->GetHostResolver()));
int net_result = resolver_->Resolve(
- request_info, &address_list_,
+ request_info,
+ net::DEFAULT_PRIORITY,
+ &address_list_,
base::Bind(&PepperTCPSocket::OnResolveCompleted, base::Unretained(this)),
net::BoundNetLog());
if (net_result != net::ERR_IO_PENDING)
@@ -141,16 +143,16 @@ void PepperTCPSocket::SSLHandshake(
connection_state_ = SSL_HANDSHAKE_IN_PROGRESS;
// TODO(raymes,rsleevi): Use trusted/untrusted certificates when connecting.
- net::ClientSocketHandle* handle = new net::ClientSocketHandle();
- handle->set_socket(socket_.release());
+ scoped_ptr<net::ClientSocketHandle> handle(new net::ClientSocketHandle());
+ handle->SetSocket(socket_.Pass());
net::ClientSocketFactory* factory =
net::ClientSocketFactory::GetDefaultFactory();
net::HostPortPair host_port_pair(server_name, server_port);
net::SSLClientSocketContext ssl_context;
ssl_context.cert_verifier = manager_->GetCertVerifier();
ssl_context.transport_security_state = manager_->GetTransportSecurityState();
- socket_.reset(factory->CreateSSLClientSocket(
- handle, host_port_pair, manager_->ssl_config(), ssl_context));
+ socket_ = factory->CreateSSLClientSocket(
+ handle.Pass(), host_port_pair, manager_->ssl_config(), ssl_context);
if (!socket_) {
LOG(WARNING) << "Failed to create an SSL client socket.";
OnSSLHandshakeCompleted(net::ERR_UNEXPECTED);
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket.h b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket.h
deleted file mode 100644
index 986afb015bb..00000000000
--- a/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket.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_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TCP_SOCKET_H_
-#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TCP_SOCKET_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "net/base/address_list.h"
-#include "net/base/completion_callback.h"
-#include "ppapi/c/pp_stdint.h"
-#include "ppapi/c/ppb_tcp_socket.h"
-
-struct PP_NetAddress_Private;
-
-namespace ppapi {
-class PPB_X509Certificate_Fields;
-class SocketOptionData;
-}
-
-namespace net {
-class DrainableIOBuffer;
-class IOBuffer;
-class SingleRequestHostResolver;
-class StreamSocket;
-class X509Certificate;
-}
-
-namespace content {
-class PepperMessageFilter;
-
-// PepperTCPSocket is used by PepperMessageFilter to handle requests from
-// the Pepper TCP socket API (PPB_TCPSocket and PPB_TCPSocket_Private).
-class PepperTCPSocket {
- public:
- PepperTCPSocket(PepperMessageFilter* manager,
- int32 routing_id,
- uint32 plugin_dispatcher_id,
- uint32 socket_id,
- bool private_api);
-
- // Used for creation already connected sockets. Takes ownership of
- // |socket|.
- PepperTCPSocket(PepperMessageFilter* manager,
- int32 routing_id,
- uint32 plugin_dispatcher_id,
- uint32 socket_id,
- net::StreamSocket* socket,
- bool private_api);
- ~PepperTCPSocket();
-
- int routing_id() { return routing_id_; }
- bool private_api() const { return private_api_; }
-
- void Connect(const std::string& host, uint16_t port);
- void ConnectWithNetAddress(const PP_NetAddress_Private& net_addr);
- void SSLHandshake(
- const std::string& server_name,
- uint16_t server_port,
- const std::vector<std::vector<char> >& trusted_certs,
- const std::vector<std::vector<char> >& untrusted_certs);
- void Read(int32 bytes_to_read);
- void Write(const std::string& data);
- void SetOption(PP_TCPSocket_Option name,
- const ppapi::SocketOptionData& value);
-
- void SendConnectACKError(int32_t error);
-
- // Extracts the certificate field data from a |net::X509Certificate| into
- // |PPB_X509Certificate_Fields|.
- static bool GetCertificateFields(const net::X509Certificate& cert,
- ppapi::PPB_X509Certificate_Fields* fields);
- // Extracts the certificate field data from the DER representation of a
- // certificate into |PPB_X509Certificate_Fields|.
- static bool GetCertificateFields(const char* der,
- uint32_t length,
- ppapi::PPB_X509Certificate_Fields* fields);
-
- private:
- enum ConnectionState {
- // Before a connection is successfully established (including a previous
- // connect request failed).
- BEFORE_CONNECT,
- // There is a connect request that is pending.
- CONNECT_IN_PROGRESS,
- // A connection has been successfully established.
- CONNECTED,
- // There is an SSL handshake request that is pending.
- SSL_HANDSHAKE_IN_PROGRESS,
- // An SSL connection has been successfully established.
- SSL_CONNECTED,
- // An SSL handshake has failed.
- SSL_HANDSHAKE_FAILED
- };
-
- void StartConnect(const net::AddressList& addresses);
-
- void SendReadACKError(int32_t error);
- void SendWriteACKError(int32_t error);
- void SendSSLHandshakeACK(bool succeeded);
- void SendSetOptionACK(int32_t result);
-
- void OnResolveCompleted(int net_result);
- void OnConnectCompleted(int net_result);
- void OnSSLHandshakeCompleted(int net_result);
- void OnReadCompleted(int net_result);
- void OnWriteCompleted(int net_result);
-
- bool IsConnected() const;
- bool IsSsl() const;
-
- // Actually does a write from |write_buffer_|; possibly called many times for
- // each |Write()|.
- void DoWrite();
-
- PepperMessageFilter* manager_;
- int32 routing_id_;
- uint32 plugin_dispatcher_id_;
- uint32 socket_id_;
- bool private_api_;
-
- ConnectionState connection_state_;
- bool end_of_file_reached_;
-
- scoped_ptr<net::SingleRequestHostResolver> resolver_;
- net::AddressList address_list_;
-
- scoped_ptr<net::StreamSocket> socket_;
-
- scoped_refptr<net::IOBuffer> read_buffer_;
-
- // |StreamSocket::Write()| may not always write the full buffer, but we would
- // rather have our |Write()| do so whenever possible. To do this, we may have
- // to call the former multiple times for each of the latter. This entails
- // using a |DrainableIOBuffer|, which requires an underlying base |IOBuffer|.
- scoped_refptr<net::IOBuffer> write_buffer_base_;
- scoped_refptr<net::DrainableIOBuffer> write_buffer_;
-
- DISALLOW_COPY_AND_ASSIGN(PepperTCPSocket);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TCP_SOCKET_H_
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
new file mode 100644
index 00000000000..f943f39eb9e
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
@@ -0,0 +1,979 @@
+// Copyright 2013 The Chromium Authors. All rights 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_tcp_socket_message_filter.h"
+
+#include <cstring>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "build/build_config.h"
+#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
+#include "content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h"
+#include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/resource_context.h"
+#include "content/public/common/socket_permission_request.h"
+#include "net/base/address_family.h"
+#include "net/base/host_port_pair.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/dns/single_request_host_resolver.h"
+#include "net/socket/client_socket_factory.h"
+#include "net/socket/client_socket_handle.h"
+#include "net/socket/ssl_client_socket.h"
+#include "net/socket/tcp_client_socket.h"
+#include "ppapi/host/dispatch_host_message.h"
+#include "ppapi/host/error_conversion.h"
+#include "ppapi/host/ppapi_host.h"
+#include "ppapi/host/resource_host.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/tcp_socket_resource_base.h"
+#include "ppapi/shared_impl/private/net_address_private_impl.h"
+
+using ppapi::NetAddressPrivateImpl;
+using ppapi::host::NetErrorToPepperError;
+using ppapi::proxy::TCPSocketResourceBase;
+using ppapi::TCPSocketState;
+using ppapi::TCPSocketVersion;
+
+namespace {
+
+size_t g_num_instances = 0;
+
+} // namespace
+
+namespace content {
+
+PepperTCPSocketMessageFilter::PepperTCPSocketMessageFilter(
+ ContentBrowserPepperHostFactory* factory,
+ BrowserPpapiHostImpl* host,
+ PP_Instance instance,
+ TCPSocketVersion version)
+ : version_(version),
+ external_plugin_(host->external_plugin()),
+ render_process_id_(0),
+ render_view_id_(0),
+ ppapi_host_(host->GetPpapiHost()),
+ factory_(factory),
+ instance_(instance),
+ state_(TCPSocketState::INITIAL),
+ end_of_file_reached_(false),
+ bind_input_addr_(NetAddressPrivateImpl::kInvalidNetAddress),
+ address_index_(0),
+ socket_(new net::TCPSocket(NULL, net::NetLog::Source())),
+ ssl_context_helper_(host->ssl_context_helper()),
+ pending_accept_(false) {
+ DCHECK(host);
+ ++g_num_instances;
+ if (!host->GetRenderViewIDsForInstance(instance,
+ &render_process_id_,
+ &render_view_id_)) {
+ NOTREACHED();
+ }
+}
+
+PepperTCPSocketMessageFilter::PepperTCPSocketMessageFilter(
+ BrowserPpapiHostImpl* host,
+ PP_Instance instance,
+ TCPSocketVersion version,
+ scoped_ptr<net::TCPSocket> socket)
+ : version_(version),
+ external_plugin_(host->external_plugin()),
+ render_process_id_(0),
+ render_view_id_(0),
+ ppapi_host_(host->GetPpapiHost()),
+ factory_(NULL),
+ instance_(instance),
+ state_(TCPSocketState::CONNECTED),
+ end_of_file_reached_(false),
+ bind_input_addr_(NetAddressPrivateImpl::kInvalidNetAddress),
+ address_index_(0),
+ socket_(socket.Pass()),
+ ssl_context_helper_(host->ssl_context_helper()),
+ pending_accept_(false) {
+ DCHECK(host);
+ DCHECK_NE(version, ppapi::TCP_SOCKET_VERSION_1_0);
+
+ ++g_num_instances;
+ if (!host->GetRenderViewIDsForInstance(instance,
+ &render_process_id_,
+ &render_view_id_)) {
+ NOTREACHED();
+ }
+}
+
+PepperTCPSocketMessageFilter::~PepperTCPSocketMessageFilter() {
+ if (socket_)
+ socket_->Close();
+ if (ssl_socket_)
+ ssl_socket_->Disconnect();
+ --g_num_instances;
+}
+
+// static
+size_t PepperTCPSocketMessageFilter::GetNumInstances() {
+ return g_num_instances;
+}
+
+scoped_refptr<base::TaskRunner>
+PepperTCPSocketMessageFilter::OverrideTaskRunnerForMessage(
+ const IPC::Message& message) {
+ switch (message.type()) {
+ case PpapiHostMsg_TCPSocket_Bind::ID:
+ case PpapiHostMsg_TCPSocket_Connect::ID:
+ case PpapiHostMsg_TCPSocket_ConnectWithNetAddress::ID:
+ case PpapiHostMsg_TCPSocket_Listen::ID:
+ return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
+ case PpapiHostMsg_TCPSocket_SSLHandshake::ID:
+ case PpapiHostMsg_TCPSocket_Read::ID:
+ case PpapiHostMsg_TCPSocket_Write::ID:
+ case PpapiHostMsg_TCPSocket_Accept::ID:
+ case PpapiHostMsg_TCPSocket_Close::ID:
+ case PpapiHostMsg_TCPSocket_SetOption::ID:
+ return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
+ }
+ return NULL;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnResourceMessageReceived(
+ const IPC::Message& msg,
+ ppapi::host::HostMessageContext* context) {
+ IPC_BEGIN_MESSAGE_MAP(PepperTCPSocketMessageFilter, msg)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+ PpapiHostMsg_TCPSocket_Bind, OnMsgBind)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+ PpapiHostMsg_TCPSocket_Connect, OnMsgConnect)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+ PpapiHostMsg_TCPSocket_ConnectWithNetAddress,
+ OnMsgConnectWithNetAddress)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+ PpapiHostMsg_TCPSocket_SSLHandshake, OnMsgSSLHandshake)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+ PpapiHostMsg_TCPSocket_Read, OnMsgRead)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+ PpapiHostMsg_TCPSocket_Write, OnMsgWrite)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+ PpapiHostMsg_TCPSocket_Listen, OnMsgListen)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
+ PpapiHostMsg_TCPSocket_Accept, OnMsgAccept)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
+ PpapiHostMsg_TCPSocket_Close, OnMsgClose)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+ PpapiHostMsg_TCPSocket_SetOption, OnMsgSetOption)
+ IPC_END_MESSAGE_MAP()
+ return PP_ERROR_FAILED;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnMsgBind(
+ const ppapi::host::HostMessageContext* context,
+ const PP_NetAddress_Private& net_addr) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ // This is only supported by PPB_TCPSocket v1.1 or above.
+ if (version_ != ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
+ NOTREACHED();
+ return PP_ERROR_NOACCESS;
+ }
+
+ if (!pepper_socket_utils::CanUseSocketAPIs(
+ external_plugin_, false /* private_api */, NULL, render_process_id_,
+ render_view_id_)) {
+ return PP_ERROR_NOACCESS;
+ }
+
+ bind_input_addr_ = net_addr;
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&PepperTCPSocketMessageFilter::DoBind, this,
+ context->MakeReplyMessageContext(), net_addr));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnMsgConnect(
+ const ppapi::host::HostMessageContext* context,
+ const std::string& host,
+ uint16_t port) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ // This is only supported by PPB_TCPSocket_Private.
+ if (!IsPrivateAPI()) {
+ NOTREACHED();
+ return PP_ERROR_NOACCESS;
+ }
+
+ SocketPermissionRequest request(SocketPermissionRequest::TCP_CONNECT,
+ host,
+ port);
+ if (!pepper_socket_utils::CanUseSocketAPIs(
+ external_plugin_, true /* private_api */, &request,
+ render_process_id_, render_view_id_)) {
+ return PP_ERROR_NOACCESS;
+ }
+
+ RenderProcessHost* render_process_host =
+ RenderProcessHost::FromID(render_process_id_);
+ if (!render_process_host)
+ return PP_ERROR_FAILED;
+ BrowserContext* browser_context = render_process_host->GetBrowserContext();
+ if (!browser_context || !browser_context->GetResourceContext())
+ return PP_ERROR_FAILED;
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&PepperTCPSocketMessageFilter::DoConnect, this,
+ context->MakeReplyMessageContext(),
+ host, port, browser_context->GetResourceContext()));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnMsgConnectWithNetAddress(
+ const ppapi::host::HostMessageContext* context,
+ const PP_NetAddress_Private& net_addr) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ content::SocketPermissionRequest request =
+ pepper_socket_utils::CreateSocketPermissionRequest(
+ content::SocketPermissionRequest::TCP_CONNECT, net_addr);
+ if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_, IsPrivateAPI(),
+ &request, render_process_id_,
+ render_view_id_)) {
+ return PP_ERROR_NOACCESS;
+ }
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&PepperTCPSocketMessageFilter::DoConnectWithNetAddress, this,
+ context->MakeReplyMessageContext(), net_addr));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnMsgSSLHandshake(
+ const ppapi::host::HostMessageContext* context,
+ const std::string& server_name,
+ uint16_t server_port,
+ const std::vector<std::vector<char> >& trusted_certs,
+ const std::vector<std::vector<char> >& untrusted_certs) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ // Allow to do SSL handshake only if currently the socket has been connected
+ // and there isn't pending read or write.
+ if (!state_.IsValidTransition(TCPSocketState::SSL_CONNECT) ||
+ read_buffer_.get() || write_buffer_base_.get() || write_buffer_.get()) {
+ return PP_ERROR_FAILED;
+ }
+
+ // TODO(raymes,rsleevi): Use trusted/untrusted certificates when connecting.
+ net::IPEndPoint peer_address;
+ if (socket_->GetPeerAddress(&peer_address) != net::OK)
+ return PP_ERROR_FAILED;
+
+ scoped_ptr<net::ClientSocketHandle> handle(new net::ClientSocketHandle());
+ handle->SetSocket(make_scoped_ptr<net::StreamSocket>(
+ new net::TCPClientSocket(socket_.Pass(), peer_address)));
+ net::ClientSocketFactory* factory =
+ net::ClientSocketFactory::GetDefaultFactory();
+ net::HostPortPair host_port_pair(server_name, server_port);
+ net::SSLClientSocketContext ssl_context;
+ ssl_context.cert_verifier = ssl_context_helper_->GetCertVerifier();
+ ssl_context.transport_security_state =
+ ssl_context_helper_->GetTransportSecurityState();
+ ssl_socket_ = factory->CreateSSLClientSocket(
+ handle.Pass(), host_port_pair, ssl_context_helper_->ssl_config(),
+ ssl_context);
+ if (!ssl_socket_) {
+ LOG(WARNING) << "Failed to create an SSL client socket.";
+ state_.CompletePendingTransition(false);
+ return PP_ERROR_FAILED;
+ }
+
+ state_.SetPendingTransition(TCPSocketState::SSL_CONNECT);
+
+ const ppapi::host::ReplyMessageContext reply_context(
+ context->MakeReplyMessageContext());
+ int net_result = ssl_socket_->Connect(
+ base::Bind(&PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted,
+ base::Unretained(this), reply_context));
+ if (net_result != net::ERR_IO_PENDING)
+ OnSSLHandshakeCompleted(reply_context, net_result);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnMsgRead(
+ const ppapi::host::HostMessageContext* context,
+ int32_t bytes_to_read) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (!state_.IsConnected() || end_of_file_reached_)
+ return PP_ERROR_FAILED;
+ if (read_buffer_.get())
+ return PP_ERROR_INPROGRESS;
+ if (bytes_to_read <= 0 ||
+ bytes_to_read > TCPSocketResourceBase::kMaxReadSize) {
+ return PP_ERROR_BADARGUMENT;
+ }
+
+ ppapi::host::ReplyMessageContext reply_context(
+ context->MakeReplyMessageContext());
+ read_buffer_ = new net::IOBuffer(bytes_to_read);
+
+ int net_result = net::ERR_FAILED;
+ if (socket_) {
+ DCHECK_EQ(state_.state(), TCPSocketState::CONNECTED);
+ net_result = socket_->Read(
+ read_buffer_.get(),
+ bytes_to_read,
+ base::Bind(&PepperTCPSocketMessageFilter::OnReadCompleted,
+ base::Unretained(this), reply_context));
+ } else if (ssl_socket_) {
+ DCHECK_EQ(state_.state(), TCPSocketState::SSL_CONNECTED);
+ net_result = ssl_socket_->Read(
+ read_buffer_.get(),
+ bytes_to_read,
+ base::Bind(&PepperTCPSocketMessageFilter::OnReadCompleted,
+ base::Unretained(this), reply_context));
+ }
+ if (net_result != net::ERR_IO_PENDING)
+ OnReadCompleted(reply_context, net_result);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnMsgWrite(
+ const ppapi::host::HostMessageContext* context,
+ const std::string& data) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (!state_.IsConnected())
+ return PP_ERROR_FAILED;
+ if (write_buffer_base_.get() || write_buffer_.get())
+ return PP_ERROR_INPROGRESS;
+
+ size_t data_size = data.size();
+ if (data_size == 0 ||
+ data_size > static_cast<size_t>(TCPSocketResourceBase::kMaxWriteSize)) {
+ return PP_ERROR_BADARGUMENT;
+ }
+
+ write_buffer_base_ = new net::IOBuffer(data_size);
+ memcpy(write_buffer_base_->data(), data.data(), data_size);
+ write_buffer_ =
+ new net::DrainableIOBuffer(write_buffer_base_.get(), data_size);
+ DoWrite(context->MakeReplyMessageContext());
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnMsgListen(
+ const ppapi::host::HostMessageContext* context,
+ int32_t backlog) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ // This is only supported by PPB_TCPSocket v1.1 or above.
+ if (version_ != ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
+ NOTREACHED();
+ return PP_ERROR_NOACCESS;
+ }
+
+ content::SocketPermissionRequest request =
+ pepper_socket_utils::CreateSocketPermissionRequest(
+ content::SocketPermissionRequest::TCP_LISTEN, bind_input_addr_);
+ if (!pepper_socket_utils::CanUseSocketAPIs(
+ external_plugin_, false /* private_api */, &request,
+ render_process_id_, render_view_id_)) {
+ return PP_ERROR_NOACCESS;
+ }
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&PepperTCPSocketMessageFilter::DoListen, this,
+ context->MakeReplyMessageContext(), backlog));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnMsgAccept(
+ const ppapi::host::HostMessageContext* context) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (pending_accept_)
+ return PP_ERROR_INPROGRESS;
+ if (state_.state() != TCPSocketState::LISTENING)
+ return PP_ERROR_FAILED;
+
+ pending_accept_ = true;
+ ppapi::host::ReplyMessageContext reply_context(
+ context->MakeReplyMessageContext());
+ int net_result = socket_->Accept(
+ &accepted_socket_,
+ &accepted_address_,
+ base::Bind(&PepperTCPSocketMessageFilter::OnAcceptCompleted,
+ base::Unretained(this), reply_context));
+ if (net_result != net::ERR_IO_PENDING)
+ OnAcceptCompleted(reply_context, net_result);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnMsgClose(
+ const ppapi::host::HostMessageContext* context) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (state_.state() == TCPSocketState::CLOSED)
+ return PP_OK;
+
+ state_.DoTransition(TCPSocketState::CLOSE, true);
+ // Make sure we get no further callbacks from |socket_| or |ssl_socket_|.
+ if (socket_) {
+ socket_->Close();
+ } else if (ssl_socket_) {
+ ssl_socket_->Disconnect();
+ }
+ return PP_OK;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnMsgSetOption(
+ const ppapi::host::HostMessageContext* context,
+ PP_TCPSocket_Option name,
+ const ppapi::SocketOptionData& value) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ switch (name) {
+ case PP_TCPSOCKET_OPTION_NO_DELAY: {
+ if (state_.state() != TCPSocketState::CONNECTED)
+ return PP_ERROR_FAILED;
+
+ bool boolean_value = false;
+ if (!value.GetBool(&boolean_value))
+ return PP_ERROR_BADARGUMENT;
+ return socket_->SetNoDelay(boolean_value) ? PP_OK : PP_ERROR_FAILED;
+ }
+ case PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE:
+ case PP_TCPSOCKET_OPTION_RECV_BUFFER_SIZE: {
+ if (state_.state() != TCPSocketState::CONNECTED)
+ return PP_ERROR_FAILED;
+
+ int32_t integer_value = 0;
+ if (!value.GetInt32(&integer_value) || integer_value <= 0)
+ return PP_ERROR_BADARGUMENT;
+
+ bool result = false;
+ if (name == PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE) {
+ if (integer_value > TCPSocketResourceBase::kMaxSendBufferSize)
+ return PP_ERROR_BADARGUMENT;
+ result = socket_->SetSendBufferSize(integer_value);
+ } else {
+ if (integer_value > TCPSocketResourceBase::kMaxReceiveBufferSize)
+ return PP_ERROR_BADARGUMENT;
+ result = socket_->SetReceiveBufferSize(integer_value);
+ }
+ return result ? PP_OK : PP_ERROR_FAILED;
+ }
+ default: {
+ NOTREACHED();
+ return PP_ERROR_BADARGUMENT;
+ }
+ }
+}
+
+void PepperTCPSocketMessageFilter::DoBind(
+ const ppapi::host::ReplyMessageContext& context,
+ const PP_NetAddress_Private& net_addr) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (state_.IsPending(TCPSocketState::BIND)) {
+ SendBindError(context, PP_ERROR_INPROGRESS);
+ return;
+ }
+ if (!state_.IsValidTransition(TCPSocketState::BIND)) {
+ SendBindError(context, PP_ERROR_FAILED);
+ return;
+ }
+
+ int pp_result = PP_OK;
+ do {
+ net::IPAddressNumber address;
+ int port;
+ if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(net_addr, &address,
+ &port)) {
+ pp_result = PP_ERROR_ADDRESS_INVALID;
+ break;
+ }
+ net::IPEndPoint bind_addr(address, port);
+
+ DCHECK(!socket_->IsValid());
+ pp_result = NetErrorToPepperError(socket_->Open(bind_addr.GetFamily()));
+ if (pp_result != PP_OK)
+ break;
+
+ pp_result = NetErrorToPepperError(socket_->SetDefaultOptionsForServer());
+ if (pp_result != PP_OK)
+ break;
+
+ pp_result = NetErrorToPepperError(socket_->Bind(bind_addr));
+ if (pp_result != PP_OK)
+ break;
+
+ net::IPEndPoint ip_end_point_local;
+ pp_result = NetErrorToPepperError(
+ socket_->GetLocalAddress(&ip_end_point_local));
+ if (pp_result != PP_OK)
+ break;
+
+ PP_NetAddress_Private local_addr =
+ NetAddressPrivateImpl::kInvalidNetAddress;
+ if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
+ ip_end_point_local.address(),
+ ip_end_point_local.port(),
+ &local_addr)) {
+ pp_result = PP_ERROR_ADDRESS_INVALID;
+ break;
+ }
+
+ SendBindReply(context, PP_OK, local_addr);
+ state_.DoTransition(TCPSocketState::BIND, true);
+ return;
+ } while (false);
+ if (socket_->IsValid())
+ socket_->Close();
+ SendBindError(context, pp_result);
+ state_.DoTransition(TCPSocketState::BIND, false);
+}
+
+void PepperTCPSocketMessageFilter::DoConnect(
+ const ppapi::host::ReplyMessageContext& context,
+ const std::string& host,
+ uint16_t port,
+ ResourceContext* resource_context) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (!state_.IsValidTransition(TCPSocketState::CONNECT)) {
+ SendConnectError(context, PP_ERROR_FAILED);
+ return;
+ }
+
+ state_.SetPendingTransition(TCPSocketState::CONNECT);
+ address_index_ = 0;
+ address_list_.clear();
+ net::HostResolver::RequestInfo request_info(net::HostPortPair(host, port));
+ resolver_.reset(new net::SingleRequestHostResolver(
+ resource_context->GetHostResolver()));
+ int net_result = resolver_->Resolve(
+ request_info,
+ net::DEFAULT_PRIORITY,
+ &address_list_,
+ base::Bind(&PepperTCPSocketMessageFilter::OnResolveCompleted,
+ base::Unretained(this), context),
+ net::BoundNetLog());
+ if (net_result != net::ERR_IO_PENDING)
+ OnResolveCompleted(context, net_result);
+}
+
+void PepperTCPSocketMessageFilter::DoConnectWithNetAddress(
+ const ppapi::host::ReplyMessageContext& context,
+ const PP_NetAddress_Private& net_addr) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (!state_.IsValidTransition(TCPSocketState::CONNECT)) {
+ SendConnectError(context, PP_ERROR_FAILED);
+ return;
+ }
+
+ state_.SetPendingTransition(TCPSocketState::CONNECT);
+
+ net::IPAddressNumber address;
+ int port;
+ if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(net_addr, &address,
+ &port)) {
+ state_.CompletePendingTransition(false);
+ SendConnectError(context, PP_ERROR_ADDRESS_INVALID);
+ return;
+ }
+
+ // Copy the single IPEndPoint to address_list_.
+ address_index_ = 0;
+ address_list_.clear();
+ address_list_.push_back(net::IPEndPoint(address, port));
+ StartConnect(context);
+}
+
+void PepperTCPSocketMessageFilter::DoWrite(
+ const ppapi::host::ReplyMessageContext& context) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(write_buffer_base_.get());
+ DCHECK(write_buffer_.get());
+ DCHECK_GT(write_buffer_->BytesRemaining(), 0);
+ DCHECK(state_.IsConnected());
+
+ int net_result = net::ERR_FAILED;
+ if (socket_) {
+ DCHECK_EQ(state_.state(), TCPSocketState::CONNECTED);
+ net_result = socket_->Write(
+ write_buffer_.get(),
+ write_buffer_->BytesRemaining(),
+ base::Bind(&PepperTCPSocketMessageFilter::OnWriteCompleted,
+ base::Unretained(this), context));
+ } else if (ssl_socket_) {
+ DCHECK_EQ(state_.state(), TCPSocketState::SSL_CONNECTED);
+ net_result = ssl_socket_->Write(
+ write_buffer_.get(),
+ write_buffer_->BytesRemaining(),
+ base::Bind(&PepperTCPSocketMessageFilter::OnWriteCompleted,
+ base::Unretained(this), context));
+ }
+ if (net_result != net::ERR_IO_PENDING)
+ OnWriteCompleted(context, net_result);
+}
+
+void PepperTCPSocketMessageFilter::DoListen(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t backlog) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (state_.IsPending(TCPSocketState::LISTEN)) {
+ SendListenReply(context, PP_ERROR_INPROGRESS);
+ return;
+ }
+ if (!state_.IsValidTransition(TCPSocketState::LISTEN)) {
+ SendListenReply(context, PP_ERROR_FAILED);
+ return;
+ }
+
+ int32_t pp_result = NetErrorToPepperError(socket_->Listen(backlog));
+ SendListenReply(context, pp_result);
+ state_.DoTransition(TCPSocketState::LISTEN, pp_result == PP_OK);
+}
+
+void PepperTCPSocketMessageFilter::OnResolveCompleted(
+ const ppapi::host::ReplyMessageContext& context,
+ int net_result) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (!state_.IsPending(TCPSocketState::CONNECT)) {
+ DCHECK(state_.state() == TCPSocketState::CLOSED);
+ SendConnectError(context, PP_ERROR_FAILED);
+ return;
+ }
+
+ if (net_result != net::OK) {
+ SendConnectError(context, NetErrorToPepperError(net_result));
+ state_.CompletePendingTransition(false);
+ return;
+ }
+
+ StartConnect(context);
+}
+
+void PepperTCPSocketMessageFilter::StartConnect(
+ const ppapi::host::ReplyMessageContext& context) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(state_.IsPending(TCPSocketState::CONNECT));
+ DCHECK_LT(address_index_, address_list_.size());
+
+ int net_result = net::OK;
+ if (!socket_->IsValid())
+ net_result = socket_->Open(address_list_[address_index_].GetFamily());
+
+ if (net_result == net::OK) {
+ net_result = socket_->Connect(
+ address_list_[address_index_],
+ base::Bind(&PepperTCPSocketMessageFilter::OnConnectCompleted,
+ base::Unretained(this), context));
+ }
+ if (net_result != net::ERR_IO_PENDING)
+ OnConnectCompleted(context, net_result);
+}
+
+void PepperTCPSocketMessageFilter::OnConnectCompleted(
+ const ppapi::host::ReplyMessageContext& context,
+ int net_result) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (!state_.IsPending(TCPSocketState::CONNECT)) {
+ DCHECK(state_.state() == TCPSocketState::CLOSED);
+ SendConnectError(context, PP_ERROR_FAILED);
+ return;
+ }
+
+ int32_t pp_result = NetErrorToPepperError(net_result);
+ do {
+ if (pp_result != PP_OK)
+ break;
+
+ net::IPEndPoint ip_end_point_local;
+ net::IPEndPoint ip_end_point_remote;
+ pp_result = NetErrorToPepperError(
+ socket_->GetLocalAddress(&ip_end_point_local));
+ if (pp_result != PP_OK)
+ break;
+ pp_result = NetErrorToPepperError(
+ socket_->GetPeerAddress(&ip_end_point_remote));
+ if (pp_result != PP_OK)
+ break;
+
+ PP_NetAddress_Private local_addr =
+ NetAddressPrivateImpl::kInvalidNetAddress;
+ PP_NetAddress_Private remote_addr =
+ NetAddressPrivateImpl::kInvalidNetAddress;
+ if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
+ ip_end_point_local.address(),
+ ip_end_point_local.port(),
+ &local_addr) ||
+ !NetAddressPrivateImpl::IPEndPointToNetAddress(
+ ip_end_point_remote.address(),
+ ip_end_point_remote.port(),
+ &remote_addr)) {
+ pp_result = PP_ERROR_ADDRESS_INVALID;
+ break;
+ }
+
+ socket_->SetDefaultOptionsForClient();
+ SendConnectReply(context, PP_OK, local_addr, remote_addr);
+ state_.CompletePendingTransition(true);
+ return;
+ } while (false);
+
+ if (version_ == ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
+ DCHECK_EQ(1u, address_list_.size());
+
+ SendConnectError(context, pp_result);
+ state_.CompletePendingTransition(false);
+ } else {
+ // We have to recreate |socket_| because it doesn't allow a second connect
+ // attempt. We won't lose any state such as bound address or set options,
+ // because in the private or v1.0 API, connect must be the first operation.
+ socket_.reset(new net::TCPSocket(NULL, net::NetLog::Source()));
+
+ if (address_index_ + 1 < address_list_.size()) {
+ DCHECK_EQ(version_, ppapi::TCP_SOCKET_VERSION_PRIVATE);
+ address_index_++;
+ StartConnect(context);
+ } else {
+ SendConnectError(context, pp_result);
+ // In order to maintain backward compatibility, allow further attempts to
+ // connect the socket.
+ state_ = TCPSocketState(TCPSocketState::INITIAL);
+ }
+ }
+}
+
+void PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted(
+ const ppapi::host::ReplyMessageContext& context,
+ int net_result) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (!state_.IsPending(TCPSocketState::SSL_CONNECT)) {
+ DCHECK(state_.state() == TCPSocketState::CLOSED);
+ SendSSLHandshakeReply(context, PP_ERROR_FAILED);
+ return;
+ }
+
+ SendSSLHandshakeReply(context, NetErrorToPepperError(net_result));
+ state_.CompletePendingTransition(net_result == net::OK);
+}
+
+void PepperTCPSocketMessageFilter::OnReadCompleted(
+ const ppapi::host::ReplyMessageContext& context,
+ int net_result) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(read_buffer_.get());
+
+ if (net_result > 0) {
+ SendReadReply(context,
+ PP_OK,
+ std::string(read_buffer_->data(), net_result));
+ } else if (net_result == 0) {
+ end_of_file_reached_ = true;
+ SendReadReply(context, PP_OK, std::string());
+ } else {
+ SendReadError(context, NetErrorToPepperError(net_result));
+ }
+ read_buffer_ = NULL;
+}
+
+void PepperTCPSocketMessageFilter::OnWriteCompleted(
+ const ppapi::host::ReplyMessageContext& context,
+ int net_result) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(write_buffer_base_.get());
+ DCHECK(write_buffer_.get());
+
+ // Note: For partial writes of 0 bytes, don't continue writing to avoid a
+ // likely infinite loop.
+ if (net_result > 0) {
+ write_buffer_->DidConsume(net_result);
+ if (write_buffer_->BytesRemaining() > 0 && state_.IsConnected()) {
+ DoWrite(context);
+ return;
+ }
+ }
+
+ if (net_result >= 0)
+ SendWriteReply(context, write_buffer_->BytesConsumed());
+ else
+ SendWriteReply(context, NetErrorToPepperError(net_result));
+
+ write_buffer_ = NULL;
+ write_buffer_base_ = NULL;
+}
+
+void PepperTCPSocketMessageFilter::OnAcceptCompleted(
+ const ppapi::host::ReplyMessageContext& context,
+ int net_result) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(pending_accept_);
+
+ pending_accept_ = false;
+
+ if (net_result != net::OK) {
+ SendAcceptError(context, NetErrorToPepperError(net_result));
+ return;
+ }
+
+ DCHECK(accepted_socket_.get());
+
+ net::IPEndPoint ip_end_point_local;
+ PP_NetAddress_Private local_addr = NetAddressPrivateImpl::kInvalidNetAddress;
+ PP_NetAddress_Private remote_addr = NetAddressPrivateImpl::kInvalidNetAddress;
+
+ int32_t pp_result =
+ NetErrorToPepperError(accepted_socket_->GetLocalAddress(
+ &ip_end_point_local));
+ if (pp_result != PP_OK) {
+ SendAcceptError(context, pp_result);
+ return;
+ }
+ if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
+ ip_end_point_local.address(),
+ ip_end_point_local.port(),
+ &local_addr) ||
+ !NetAddressPrivateImpl::IPEndPointToNetAddress(
+ accepted_address_.address(),
+ accepted_address_.port(),
+ &remote_addr)) {
+ SendAcceptError(context, PP_ERROR_ADDRESS_INVALID);
+ return;
+ }
+
+ // |factory_| is guaranteed to be non-NULL here. Only those instances created
+ // in CONNECTED state have a NULL |factory_|, while getting here requires
+ // LISTENING state.
+ scoped_ptr<ppapi::host::ResourceHost> host =
+ factory_->CreateAcceptedTCPSocket(
+ instance_, version_, accepted_socket_.Pass());
+ if (!host) {
+ SendAcceptError(context, PP_ERROR_NOSPACE);
+ return;
+ }
+ int pending_host_id = ppapi_host_->AddPendingResourceHost(host.Pass());
+ if (pending_host_id)
+ SendAcceptReply(context, PP_OK, pending_host_id, local_addr, remote_addr);
+ else
+ SendAcceptError(context, PP_ERROR_NOSPACE);
+}
+
+void PepperTCPSocketMessageFilter::SendBindReply(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result,
+ const PP_NetAddress_Private& local_addr) {
+ ppapi::host::ReplyMessageContext reply_context(context);
+ reply_context.params.set_result(pp_result);
+ SendReply(reply_context, PpapiPluginMsg_TCPSocket_BindReply(local_addr));
+}
+
+void PepperTCPSocketMessageFilter::SendBindError(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_error) {
+ SendBindReply(context, pp_error, NetAddressPrivateImpl::kInvalidNetAddress);
+}
+
+void PepperTCPSocketMessageFilter::SendConnectReply(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr) {
+ ppapi::host::ReplyMessageContext reply_context(context);
+ reply_context.params.set_result(pp_result);
+ SendReply(reply_context,
+ PpapiPluginMsg_TCPSocket_ConnectReply(local_addr, remote_addr));
+}
+
+void PepperTCPSocketMessageFilter::SendConnectError(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_error) {
+ SendConnectReply(context,
+ pp_error,
+ NetAddressPrivateImpl::kInvalidNetAddress,
+ NetAddressPrivateImpl::kInvalidNetAddress);
+}
+
+void PepperTCPSocketMessageFilter::SendSSLHandshakeReply(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result) {
+ ppapi::host::ReplyMessageContext reply_context(context);
+ reply_context.params.set_result(pp_result);
+ ppapi::PPB_X509Certificate_Fields certificate_fields;
+ if (pp_result == PP_OK) {
+ // Our socket is guaranteed to be an SSL socket if we get here.
+ net::SSLInfo ssl_info;
+ ssl_socket_->GetSSLInfo(&ssl_info);
+ if (ssl_info.cert.get()) {
+ pepper_socket_utils::GetCertificateFields(*ssl_info.cert.get(),
+ &certificate_fields);
+ }
+ }
+ SendReply(reply_context,
+ PpapiPluginMsg_TCPSocket_SSLHandshakeReply(certificate_fields));
+}
+
+void PepperTCPSocketMessageFilter::SendReadReply(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result,
+ const std::string& data) {
+ ppapi::host::ReplyMessageContext reply_context(context);
+ reply_context.params.set_result(pp_result);
+ SendReply(reply_context, PpapiPluginMsg_TCPSocket_ReadReply(data));
+}
+
+void PepperTCPSocketMessageFilter::SendReadError(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_error) {
+ SendReadReply(context, pp_error, std::string());
+}
+
+void PepperTCPSocketMessageFilter::SendWriteReply(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result) {
+ ppapi::host::ReplyMessageContext reply_context(context);
+ reply_context.params.set_result(pp_result);
+ SendReply(reply_context, PpapiPluginMsg_TCPSocket_WriteReply());
+}
+
+void PepperTCPSocketMessageFilter::SendListenReply(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result) {
+ ppapi::host::ReplyMessageContext reply_context(context);
+ reply_context.params.set_result(pp_result);
+ SendReply(reply_context, PpapiPluginMsg_TCPSocket_ListenReply());
+}
+
+void PepperTCPSocketMessageFilter::SendAcceptReply(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result,
+ int pending_host_id,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr) {
+ ppapi::host::ReplyMessageContext reply_context(context);
+ reply_context.params.set_result(pp_result);
+ SendReply(reply_context,
+ PpapiPluginMsg_TCPSocket_AcceptReply(
+ pending_host_id, local_addr, remote_addr));
+}
+
+void PepperTCPSocketMessageFilter::SendAcceptError(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_error) {
+ SendAcceptReply(context, pp_error, 0,
+ NetAddressPrivateImpl::kInvalidNetAddress,
+ NetAddressPrivateImpl::kInvalidNetAddress);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h
new file mode 100644
index 00000000000..fb34b988d3c
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h
@@ -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.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TCP_SOCKET_MESSAGE_FILTER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TCP_SOCKET_MESSAGE_FILTER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/renderer_host/pepper/ssl_context_helper.h"
+#include "content/common/content_export.h"
+#include "net/base/address_list.h"
+#include "net/base/ip_endpoint.h"
+#include "net/socket/tcp_socket.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/ppb_tcp_socket.h"
+#include "ppapi/c/private/ppb_net_address_private.h"
+#include "ppapi/host/resource_message_filter.h"
+#include "ppapi/shared_impl/ppb_tcp_socket_shared.h"
+
+namespace net {
+enum AddressFamily;
+class DrainableIOBuffer;
+class IOBuffer;
+class SingleRequestHostResolver;
+class SSLClientSocket;
+}
+
+namespace ppapi {
+class SocketOptionData;
+
+namespace host {
+class PpapiHost;
+struct ReplyMessageContext;
+}
+}
+
+namespace content {
+
+class BrowserPpapiHostImpl;
+class ContentBrowserPepperHostFactory;
+class ResourceContext;
+
+class CONTENT_EXPORT PepperTCPSocketMessageFilter
+ : public ppapi::host::ResourceMessageFilter {
+ public:
+ PepperTCPSocketMessageFilter(
+ ContentBrowserPepperHostFactory* factory,
+ BrowserPpapiHostImpl* host,
+ PP_Instance instance,
+ ppapi::TCPSocketVersion version);
+
+ // Used for creating already connected sockets.
+ PepperTCPSocketMessageFilter(
+ BrowserPpapiHostImpl* host,
+ PP_Instance instance,
+ ppapi::TCPSocketVersion version,
+ scoped_ptr<net::TCPSocket> socket);
+
+ static size_t GetNumInstances();
+
+ private:
+ virtual ~PepperTCPSocketMessageFilter();
+
+ // ppapi::host::ResourceMessageFilter overrides.
+ virtual scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
+ const IPC::Message& message) OVERRIDE;
+ virtual int32_t OnResourceMessageReceived(
+ const IPC::Message& msg,
+ ppapi::host::HostMessageContext* context) OVERRIDE;
+
+ int32_t OnMsgBind(const ppapi::host::HostMessageContext* context,
+ const PP_NetAddress_Private& net_addr);
+ int32_t OnMsgConnect(const ppapi::host::HostMessageContext* context,
+ const std::string& host,
+ uint16_t port);
+ int32_t OnMsgConnectWithNetAddress(
+ const ppapi::host::HostMessageContext* context,
+ const PP_NetAddress_Private& net_addr);
+ int32_t OnMsgSSLHandshake(
+ const ppapi::host::HostMessageContext* context,
+ const std::string& server_name,
+ uint16_t server_port,
+ const std::vector<std::vector<char> >& trusted_certs,
+ const std::vector<std::vector<char> >& untrusted_certs);
+ int32_t OnMsgRead(const ppapi::host::HostMessageContext* context,
+ int32_t bytes_to_read);
+ int32_t OnMsgWrite(const ppapi::host::HostMessageContext* context,
+ const std::string& data);
+ int32_t OnMsgListen(const ppapi::host::HostMessageContext* context,
+ int32_t backlog);
+ int32_t OnMsgAccept(const ppapi::host::HostMessageContext* context);
+ int32_t OnMsgClose(const ppapi::host::HostMessageContext* context);
+ int32_t OnMsgSetOption(const ppapi::host::HostMessageContext* context,
+ PP_TCPSocket_Option name,
+ const ppapi::SocketOptionData& value);
+
+ void DoBind(const ppapi::host::ReplyMessageContext& context,
+ const PP_NetAddress_Private& net_addr);
+ void DoConnect(const ppapi::host::ReplyMessageContext& context,
+ const std::string& host,
+ uint16_t port,
+ ResourceContext* resource_context);
+ void DoConnectWithNetAddress(
+ const ppapi::host::ReplyMessageContext& context,
+ const PP_NetAddress_Private& net_addr);
+ void DoWrite(const ppapi::host::ReplyMessageContext& context);
+ void DoListen(const ppapi::host::ReplyMessageContext& context,
+ int32_t backlog);
+
+ void OnResolveCompleted(const ppapi::host::ReplyMessageContext& context,
+ int net_result);
+ void StartConnect(const ppapi::host::ReplyMessageContext& context);
+
+ void OnConnectCompleted(const ppapi::host::ReplyMessageContext& context,
+ int net_result);
+ void OnSSLHandshakeCompleted(const ppapi::host::ReplyMessageContext& context,
+ int net_result);
+ void OnReadCompleted(const ppapi::host::ReplyMessageContext& context,
+ int net_result);
+ void OnWriteCompleted(const ppapi::host::ReplyMessageContext& context,
+ int net_result);
+ void OnAcceptCompleted(const ppapi::host::ReplyMessageContext& context,
+ int net_result);
+
+ void SendBindReply(const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result,
+ const PP_NetAddress_Private& local_addr);
+ void SendBindError(const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_error);
+ void SendConnectReply(const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr);
+ void SendConnectError(const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_error);
+ void SendSSLHandshakeReply(const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result);
+ void SendReadReply(const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result,
+ const std::string& data);
+ void SendReadError(const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_error);
+ void SendWriteReply(const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result);
+ void SendListenReply(const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result);
+ void SendAcceptReply(const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result,
+ int pending_host_id,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr);
+ void SendAcceptError(const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_error);
+
+ bool IsPrivateAPI() const {
+ return version_ == ppapi::TCP_SOCKET_VERSION_PRIVATE;
+ }
+
+ // The following fields are used on both the UI and IO thread.
+ const ppapi::TCPSocketVersion version_;
+
+ // The following fields are used only on the UI thread.
+ const bool external_plugin_;
+
+ int render_process_id_;
+ int render_view_id_;
+
+ // The following fields are used only on the IO thread.
+ // Non-owning ptr.
+ ppapi::host::PpapiHost* ppapi_host_;
+ // Non-owning ptr.
+ ContentBrowserPepperHostFactory* factory_;
+ PP_Instance instance_;
+
+ ppapi::TCPSocketState state_;
+ bool end_of_file_reached_;
+
+ // This is the address requested to bind. Please note that this is not the
+ // bound address. For example, |bind_input_addr_| may have port set to 0.
+ // It is used to check permission for listening.
+ PP_NetAddress_Private bind_input_addr_;
+
+ scoped_ptr<net::SingleRequestHostResolver> resolver_;
+
+ // |address_list_| may store multiple addresses when
+ // PPB_TCPSocket_Private.Connect() is used, which involves name resolution.
+ // In that case, we will try each address in the list until a connection is
+ // successfully established.
+ net::AddressList address_list_;
+ // Where we are in the above list.
+ size_t address_index_;
+
+ // Non-null unless an SSL connection is requested.
+ scoped_ptr<net::TCPSocket> socket_;
+ // Non-null if an SSL connection is requested.
+ scoped_ptr<net::SSLClientSocket> ssl_socket_;
+
+ scoped_refptr<net::IOBuffer> read_buffer_;
+
+ // TCPSocket::Write() may not always write the full buffer, but we would
+ // rather have our DoWrite() do so whenever possible. To do this, we may have
+ // to call the former multiple times for each of the latter. This entails
+ // using a DrainableIOBuffer, which requires an underlying base IOBuffer.
+ scoped_refptr<net::IOBuffer> write_buffer_base_;
+ scoped_refptr<net::DrainableIOBuffer> write_buffer_;
+ scoped_refptr<SSLContextHelper> ssl_context_helper_;
+
+ bool pending_accept_;
+ scoped_ptr<net::TCPSocket> accepted_socket_;
+ net::IPEndPoint accepted_address_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperTCPSocketMessageFilter);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TCP_SOCKET_MESSAGE_FILTER_H_
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc b/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc
index 7453fd2886a..3127ed278fd 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc
@@ -28,8 +28,8 @@
#include "ppapi/shared_impl/private/net_address_private_impl.h"
#include "ppapi/shared_impl/socket_option_data.h"
-using ppapi::host::NetErrorToPepperError;
using ppapi::NetAddressPrivateImpl;
+using ppapi::host::NetErrorToPepperError;
namespace {
@@ -173,7 +173,7 @@ int32_t PepperUDPSocketMessageFilter::OnMsgBind(
pepper_socket_utils::CreateSocketPermissionRequest(
SocketPermissionRequest::UDP_BIND, addr);
if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_, private_api_,
- request, render_process_id_,
+ &request, render_process_id_,
render_view_id_)) {
return PP_ERROR_NOACCESS;
}
@@ -236,7 +236,7 @@ int32_t PepperUDPSocketMessageFilter::OnMsgSendTo(
pepper_socket_utils::CreateSocketPermissionRequest(
SocketPermissionRequest::UDP_SEND_TO, addr);
if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_, private_api_,
- request, render_process_id_,
+ &request, render_process_id_,
render_view_id_)) {
return PP_ERROR_NOACCESS;
}
diff --git a/chromium/content/browser/renderer_host/pepper/ssl_context_helper.cc b/chromium/content/browser/renderer_host/pepper/ssl_context_helper.cc
new file mode 100644
index 00000000000..3b92e6d0c16
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/ssl_context_helper.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/renderer_host/pepper/ssl_context_helper.h"
+
+#include "net/cert/cert_verifier.h"
+#include "net/http/transport_security_state.h"
+
+namespace content {
+
+SSLContextHelper::SSLContextHelper() {
+}
+
+SSLContextHelper::~SSLContextHelper() {
+}
+
+net::CertVerifier* SSLContextHelper::GetCertVerifier() {
+ if (!cert_verifier_)
+ cert_verifier_.reset(net::CertVerifier::CreateDefault());
+ return cert_verifier_.get();
+}
+
+net::TransportSecurityState* SSLContextHelper::GetTransportSecurityState() {
+ if (!transport_security_state_)
+ transport_security_state_.reset(new net::TransportSecurityState());
+ return transport_security_state_.get();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/ssl_context_helper.h b/chromium/content/browser/renderer_host/pepper/ssl_context_helper.h
new file mode 100644
index 00000000000..f1da2a6ee1d
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/ssl_context_helper.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_PEPPER_SSL_CONTEXT_HELPER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_SSL_CONTEXT_HELPER_H_
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/ssl/ssl_config_service.h"
+
+namespace net {
+class CertVerifier;
+class TransportSecurityState;
+}
+
+namespace content {
+
+class SSLContextHelper : public base::RefCounted<SSLContextHelper> {
+ public:
+ SSLContextHelper();
+
+ net::CertVerifier* GetCertVerifier();
+ net::TransportSecurityState* GetTransportSecurityState();
+ const net::SSLConfig& ssl_config() { return ssl_config_; }
+
+ private:
+ friend class base::RefCounted<SSLContextHelper>;
+
+ ~SSLContextHelper();
+
+ // This is lazily created. Users should use GetCertVerifier to retrieve it.
+ scoped_ptr<net::CertVerifier> cert_verifier_;
+ // This is lazily created. Users should use GetTransportSecurityState to
+ // retrieve it.
+ scoped_ptr<net::TransportSecurityState> transport_security_state_;
+
+ // The default SSL configuration settings are used, as opposed to Chrome's SSL
+ // settings.
+ net::SSLConfig ssl_config_;
+
+ DISALLOW_COPY_AND_ASSIGN(SSLContextHelper);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_PEPPER_SSL_CONTEXT_HELPER_H_
diff --git a/chromium/content/browser/renderer_host/render_frame_host_impl.cc b/chromium/content/browser/renderer_host/render_frame_host_impl.cc
index ea511d0b8c3..ec621c10dca 100644
--- a/chromium/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_frame_host_impl.cc
@@ -4,31 +4,64 @@
#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 swapped_out)
+ bool is_swapped_out)
: render_view_host_(render_view_host),
- routing_id_(routing_id) {
+ 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) {
- // Use the RenderViewHost object to send the message. It inherits it from
- // RenderWidgetHost, which ultimately uses the current process's |Send|.
- return render_view_host_->Send(message);
+ return GetProcess()->Send(message);
}
bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
- // Pass the message up to the RenderViewHost, until we have enough
- // infrastructure to start processing messages in this object.
- return render_view_host_->OnMessageReceived(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
index bb94c8e63c2..78df3331efd 100644
--- a/chromium/content/browser/renderer_host/render_frame_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_frame_host_impl.h
@@ -10,14 +10,16 @@
namespace content {
+class RenderProcessHost;
class RenderViewHostImpl;
class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost {
public:
- RenderFrameHostImpl(
- RenderViewHostImpl* render_view_host,
- int routing_id,
- bool swapped_out);
+ 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
@@ -26,12 +28,16 @@ class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost {
// IPC::Listener
virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
- int routing_id() { return routing_id_; }
+ void Init();
+ RenderProcessHost* GetProcess() const;
+ int routing_id() const { return routing_id_; }
private:
- RenderViewHostImpl* render_view_host_;
+ 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);
};
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 9ee8036e044..de64924d717 100644
--- a/chromium/content/browser/renderer_host/render_process_host_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_browsertest.cc
@@ -8,7 +8,7 @@
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/test_notification_tracker.h"
-#include "content/shell/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
diff --git a/chromium/content/browser/renderer_host/render_process_host_impl.cc b/chromium/content/browser/renderer_host/render_process_host_impl.cc
index 2dd784a4e69..73cb5e11f9c 100644
--- a/chromium/content/browser/renderer_host/render_process_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_impl.cc
@@ -52,6 +52,7 @@
#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/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/shader_disk_cache.h"
@@ -60,6 +61,7 @@
#include "content/browser/indexed_db/indexed_db_dispatcher_host.h"
#include "content/browser/loader/resource_message_filter.h"
#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/mime_registry_message_filter.h"
#include "content/browser/plugin_service_impl.h"
@@ -91,6 +93,8 @@
#include "content/browser/renderer_host/socket_stream_dispatcher_host.h"
#include "content/browser/renderer_host/text_input_client_message_filter.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_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"
@@ -111,6 +115,7 @@
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_process_host_factory.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"
#include "content/public/browser/user_metrics.h"
#include "content/public/common/content_constants.h"
@@ -118,8 +123,6 @@
#include "content/public/common/process_type.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/url_constants.h"
-#include "content/renderer/render_process_impl.h"
-#include "content/renderer/render_thread_impl.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_logging.h"
@@ -129,6 +132,7 @@
#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/gfx/switches.h"
#include "ui/gl/gl_switches.h"
#include "webkit/browser/fileapi/sandbox_file_system_backend.h"
#include "webkit/common/resource_type.h"
@@ -157,8 +161,6 @@ static const char* kSiteProcessMapKeyName = "content_site_process_map";
namespace content {
namespace {
-base::MessageLoop* g_in_process_thread;
-
void CacheShaderInfo(int32 id, base::FilePath path) {
ShaderCacheFactory::GetInstance()->SetCacheInfo(id, path);
}
@@ -167,88 +169,30 @@ void RemoveShaderInfo(int32 id) {
ShaderCacheFactory::GetInstance()->RemoveCacheInfo(id);
}
-} // namespace
-
-#if !defined(CHROME_MULTIPLE_DLL)
-
-// This class creates the IO thread for the renderer when running in
-// single-process mode. It's not used in multi-process mode.
-class RendererMainThread : public base::Thread {
- public:
- explicit RendererMainThread(const std::string& channel_id)
- : Thread("Chrome_InProcRendererThread"),
- channel_id_(channel_id) {
- }
-
- virtual ~RendererMainThread() {
- Stop();
- }
-
- protected:
- virtual void Init() OVERRIDE {
- render_process_.reset(new RenderProcessImpl());
- new RenderThreadImpl(channel_id_);
- g_in_process_thread = message_loop();
- }
-
- virtual void CleanUp() OVERRIDE {
- g_in_process_thread = NULL;
- render_process_.reset();
-
- // It's a little lame to manually set this flag. But the single process
- // RendererThread will receive the WM_QUIT. We don't need to assert on
- // this thread, so just force the flag manually.
- // If we want to avoid this, we could create the InProcRendererThread
- // directly with _beginthreadex() rather than using the Thread class.
- // We used to set this flag in the Init function above. However there
- // other threads like WebThread which are created by this thread
- // which resets this flag. Please see Thread::StartWithOptions. Setting
- // this flag to true in Cleanup works around these problems.
- SetThreadWasQuitProperly(true);
- }
-
- private:
- std::string channel_id_;
- scoped_ptr<RenderProcess> render_process_;
-
- DISALLOW_COPY_AND_ASSIGN(RendererMainThread);
-};
-
-#endif
-
-namespace {
-
-// Helper class that we pass to ResourceMessageFilter so that it can find the
-// right net::URLRequestContext for a request.
-class RendererURLRequestContextSelector
- : public ResourceMessageFilter::URLRequestContextSelector {
- public:
- RendererURLRequestContextSelector(BrowserContext* browser_context,
- int render_child_id)
- : request_context_(browser_context->GetRequestContextForRenderProcess(
- render_child_id)),
- media_request_context_(
- browser_context->GetMediaRequestContextForRenderProcess(
- render_child_id)) {
- }
-
- virtual net::URLRequestContext* GetRequestContext(
- ResourceType::Type resource_type) OVERRIDE {
- net::URLRequestContextGetter* request_context = request_context_.get();
- // If the request has resource type of ResourceType::MEDIA, we use a request
- // context specific to media for handling it because these resources have
- // specific needs for caching.
- if (resource_type == ResourceType::MEDIA)
- request_context = media_request_context_.get();
- return request_context->GetURLRequestContext();
- }
-
- private:
- virtual ~RendererURLRequestContextSelector() {}
+net::URLRequestContext* GetRequestContext(
+ scoped_refptr<net::URLRequestContextGetter> request_context,
+ scoped_refptr<net::URLRequestContextGetter> media_request_context,
+ ResourceType::Type resource_type) {
+ // If the request has resource type of ResourceType::MEDIA, we use a request
+ // context specific to media for handling it because these resources have
+ // specific needs for caching.
+ if (resource_type == ResourceType::MEDIA)
+ return media_request_context->GetURLRequestContext();
+ return request_context->GetURLRequestContext();
+}
- scoped_refptr<net::URLRequestContextGetter> request_context_;
- scoped_refptr<net::URLRequestContextGetter> media_request_context_;
-};
+void GetContexts(
+ ResourceContext* resource_context,
+ scoped_refptr<net::URLRequestContextGetter> request_context,
+ scoped_refptr<net::URLRequestContextGetter> media_request_context,
+ const ResourceHostMsg_Request& request,
+ ResourceContext** resource_context_out,
+ net::URLRequestContext** request_context_out) {
+ *resource_context_out = resource_context;
+ *request_context_out =
+ GetRequestContext(request_context, media_request_context,
+ request.resource_type);
+}
// the global list of all renderer processes
base::LazyInstance<IDMap<RenderProcessHost> >::Leaky
@@ -339,6 +283,20 @@ class RendererSandboxedProcessLauncherDelegate
} // namespace
+RendererMainThreadFactoryFunction g_renderer_main_thread_factory = NULL;
+
+void RenderProcessHost::RegisterRendererMainThreadFactory(
+ RendererMainThreadFactoryFunction create) {
+ g_renderer_main_thread_factory = create;
+}
+
+base::MessageLoop* g_in_process_thread;
+
+base::MessageLoop*
+ RenderProcessHostImpl::GetInProcessRendererThreadForTesting() {
+ return g_in_process_thread;
+}
+
// Stores the maximum number of renderer processes the content module can
// create.
static size_t g_max_renderer_count_override = 0;
@@ -511,15 +469,14 @@ bool RenderProcessHostImpl::Init() {
CreateMessageFilters();
// Single-process mode not supported in multiple-dll mode currently.
-#if !defined(CHROME_MULTIPLE_DLL)
- if (run_renderer_in_process()) {
+ if (run_renderer_in_process() && 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
// thread in the renderer process runs the WebKit code and can sometimes
// make blocking calls to the UI thread (i.e. this thread), they need to run
// on separate threads.
- in_process_renderer_.reset(new RendererMainThread(channel_id));
+ in_process_renderer_.reset(g_renderer_main_thread_factory(channel_id));
base::Thread::Options options;
#if defined(OS_WIN) && !defined(OS_MACOSX)
@@ -532,10 +489,10 @@ bool RenderProcessHostImpl::Init() {
#endif
in_process_renderer_->StartWithOptions(options);
+ g_in_process_thread = in_process_renderer_->message_loop();
+
OnProcessLaunched(); // Fake a callback that the process is ready.
- } else
-#endif // !CHROME_MULTIPLE_DLL
- {
+ } else {
// Build command line for renderer. We call AppendRendererCommandLine()
// first so the process type argument will appear first.
CommandLine* cmd_line = new CommandLine(renderer_path);
@@ -552,7 +509,7 @@ bool RenderProcessHostImpl::Init() {
new RendererSandboxedProcessLauncherDelegate,
#elif defined(OS_POSIX)
renderer_prefix.empty(),
- base::EnvironmentVector(),
+ base::EnvironmentMap(),
channel_->TakeClientFileDescriptor(),
#endif
cmd_line,
@@ -604,12 +561,21 @@ void RenderProcessHostImpl::CreateMessageFilters() {
BrowserContext* browser_context = GetBrowserContext();
ResourceContext* resource_context = browser_context->GetResourceContext();
+ scoped_refptr<net::URLRequestContextGetter> request_context(
+ browser_context->GetRequestContextForRenderProcess(GetID()));
+ scoped_refptr<net::URLRequestContextGetter> media_request_context(
+ browser_context->GetMediaRequestContextForRenderProcess(GetID()));
+
+ ResourceMessageFilter::GetContextsCallback get_contexts_callback(
+ base::Bind(&GetContexts, browser_context->GetResourceContext(),
+ request_context, media_request_context));
+
ResourceMessageFilter* resource_message_filter = new ResourceMessageFilter(
- GetID(), PROCESS_TYPE_RENDERER, resource_context,
+ GetID(), PROCESS_TYPE_RENDERER,
storage_partition_impl_->GetAppCacheService(),
ChromeBlobStorageContext::GetFor(browser_context),
storage_partition_impl_->GetFileSystemContext(),
- new RendererURLRequestContextSelector(browser_context, GetID()));
+ get_contexts_callback);
channel_->AddFilter(resource_message_filter);
MediaStreamManager* media_stream_manager =
@@ -617,13 +583,16 @@ void RenderProcessHostImpl::CreateMessageFilters() {
channel_->AddFilter(new AudioInputRendererHost(
audio_manager,
media_stream_manager,
- BrowserMainLoop::GetInstance()->audio_mirroring_manager()));
+ BrowserMainLoop::GetInstance()->audio_mirroring_manager(),
+ BrowserMainLoop::GetInstance()->user_input_monitor()));
channel_->AddFilter(new AudioRendererHost(
- GetID(), audio_manager,
+ GetID(),
+ audio_manager,
BrowserMainLoop::GetInstance()->audio_mirroring_manager(),
- media_internals, media_stream_manager));
+ media_internals,
+ media_stream_manager));
channel_->AddFilter(
- new MIDIHost(BrowserMainLoop::GetInstance()->midi_manager()));
+ 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(
@@ -636,6 +605,8 @@ void RenderProcessHostImpl::CreateMessageFilters() {
channel_->AddFilter(new IndexedDBDispatcherHost(
GetID(),
storage_partition_impl_->GetIndexedDBContext()));
+ channel_->AddFilter(new ServiceWorkerDispatcherHost(
+ storage_partition_impl_->GetServiceWorkerContext()));
if (IsGuest()) {
if (!g_browser_plugin_geolocation_context.Get().get()) {
g_browser_plugin_geolocation_context.Get() =
@@ -660,8 +631,6 @@ void RenderProcessHostImpl::CreateMessageFilters() {
new DeviceRequestMessageFilter(resource_context, media_stream_manager));
#endif
#if defined(ENABLE_PLUGINS)
- // TODO(raymes): PepperMessageFilter should be removed from here.
- channel_->AddFilter(new PepperMessageFilter(GetID(), browser_context));
channel_->AddFilter(new PepperRendererConnection(GetID()));
#endif
#if defined(ENABLE_INPUT_SPEECH)
@@ -685,12 +654,19 @@ void RenderProcessHostImpl::CreateMessageFilters() {
channel_->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_);
#endif
+ SocketStreamDispatcherHost::GetRequestContextCallback
+ request_context_callback(
+ base::Bind(&GetRequestContext, request_context,
+ media_request_context));
+
SocketStreamDispatcherHost* socket_stream_dispatcher_host =
- new SocketStreamDispatcherHost(GetID(),
- new RendererURLRequestContextSelector(browser_context, GetID()),
- resource_context);
+ new SocketStreamDispatcherHost(
+ GetID(), request_context_callback, resource_context);
channel_->AddFilter(socket_stream_dispatcher_host);
channel_->AddFilter(new WorkerMessageFilter(
@@ -856,6 +832,15 @@ void RenderProcessHostImpl::AppendRendererCommandLine(
field_trial_states);
}
+ if (content::IsThreadedCompositingEnabled())
+ command_line->AppendSwitch(switches::kEnableThreadedCompositing);
+
+ if (content::IsDelegatedRendererEnabled())
+ command_line->AppendSwitch(switches::kEnableDelegatedRenderer);
+
+ if (content::IsDeadlineSchedulingEnabled())
+ command_line->AppendSwitch(switches::kEnableDeadlineScheduling);
+
GetContentClient()->browser()->AppendExtraCommandLineSwitches(
command_line, GetID());
@@ -875,6 +860,8 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kAudioBufferSize,
switches::kAuditAllHandles,
switches::kAuditHandles,
+ switches::kBlockCrossSiteDocuments,
+ switches::kDirectNPAPIRequests,
switches::kDisable3DAPIs,
switches::kDisableAcceleratedCompositing,
switches::kDisableAcceleratedVideoDecode,
@@ -882,6 +869,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kDisableAudio,
switches::kDisableBreakpad,
switches::kDisableDatabases,
+ switches::kDisableDeadlineScheduling,
switches::kDisableDelegatedRenderer,
switches::kDisableDesktopNotifications,
switches::kDisableDeviceOrientation,
@@ -894,7 +882,6 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kDisableHistogramCustomizer,
switches::kDisableLocalStorage,
switches::kDisableLogging,
- switches::kDisableNewDialogStyle,
switches::kDisableSeccompFilterSandbox,
switches::kDisableSessionStorage,
switches::kDisableSharedWorkers,
@@ -908,7 +895,9 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kDisableWebAudio,
#if defined(ENABLE_WEBRTC)
switches::kDisableDeviceEnumeration,
- switches::kEnableSCTPDataChannels,
+ switches::kDisableSCTPDataChannels,
+ switches::kDisableWebRtcHWDecoding,
+ switches::kDisableWebRtcHWEncoding,
#endif
switches::kEnableWebAnimationsCSS,
switches::kEnableWebAnimationsSVG,
@@ -921,10 +910,15 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kEnableBrowserInputController,
switches::kEnableBrowserPluginForAllViewTypes,
switches::kEnableDCHECK,
+ switches::kEnableDeadlineScheduling,
switches::kEnableDelegatedRenderer,
switches::kEnableEncryptedMedia,
switches::kDisableLegacyEncryptedMedia,
switches::kOverrideEncryptedMediaCanPlayType,
+#if defined(OS_ANDROID)
+ switches::kEnableMediaDrm,
+ switches::kMediaDrmEnableNonCompositing,
+#endif
switches::kEnableExperimentalWebPlatformFeatures,
switches::kEnableFixedLayout,
switches::kEnableDeferredImageDecoding,
@@ -932,7 +926,12 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kEnableGPUClientLogging,
switches::kEnableGpuClientTracing,
switches::kEnableGpuBenchmarking,
+#if defined(OS_WIN)
+ switches::kEnableHighResolutionTime,
+#endif
+ switches::kEnableMP3StreamParser,
switches::kEnableMemoryBenchmarking,
+ switches::kEnableOverlayFullscreenVideo,
switches::kEnableOverlayScrollbars,
switches::kEnableSkiaBenchmarking,
switches::kEnableLogging,
@@ -942,13 +941,11 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
#if defined(ENABLE_WEBRTC)
switches::kEnableWebRtcAecRecordings,
switches::kEnableWebRtcTcpServerSocket,
- switches::kEnableWebRtcHWDecoding,
#endif
switches::kDisableWebKitMediaSource,
switches::kEnableOverscrollNotifications,
switches::kEnableStrictSiteIsolation,
switches::kDisableFullScreen,
- switches::kEnableNewDialogStyle,
#if defined(ENABLE_PLUGINS)
switches::kEnablePepperTesting,
switches::kDisablePepper3d,
@@ -981,7 +978,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kEnableViewport,
switches::kEnableInbandTextTracks,
switches::kEnableOpusPlayback,
- switches::kEnableVp8AlphaPlayback,
+ switches::kDisableVp8AlphaPlayback,
switches::kEnableEac3Playback,
switches::kForceDeviceScaleFactor,
switches::kFullMemoryCrashReport,
@@ -1030,19 +1027,21 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kWebCoreLogChannels,
switches::kEnableWebGLDraftExtensions,
switches::kEnableHTMLImports,
+ switches::kEnableInputModeAttribute,
switches::kTraceToConsole,
- switches::kEnableDeviceMotion,
-#if defined(OS_ANDROID)
switches::kDisableDeviceMotion,
-#endif
// 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::kDisableImplSidePainting,
+ cc::switches::kDisableLCDText,
+ cc::switches::kDisableMapImage,
cc::switches::kDisableThreadedAnimation,
cc::switches::kEnableImplSidePainting,
+ cc::switches::kEnableLCDText,
+ cc::switches::kEnableMapImage,
cc::switches::kEnablePartialSwap,
cc::switches::kEnablePerTilePainting,
cc::switches::kEnablePinchVirtualViewport,
@@ -1066,7 +1065,6 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
cc::switches::kTopControlsHideThreshold,
cc::switches::kTopControlsShowThreshold,
cc::switches::kTraceOverdraw,
- cc::switches::kUseMapImage,
};
renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames,
arraysize(kSwitchNames));
@@ -1249,7 +1247,6 @@ bool RenderProcessHostImpl::OnMessageReceived(const IPC::Message& msg) {
// Adding single handlers for your service here is fine, but once your
// service needs more than one handler, please extract them into a new
// message filter and add that filter to CreateMessageFilters().
- IPC_MESSAGE_UNHANDLED_ERROR()
IPC_END_MESSAGE_MAP_EX()
if (!msg_is_ok) {
@@ -1613,11 +1610,6 @@ void RenderProcessHostImpl::RegisterProcessHostForSite(
map->RegisterProcess(site, process);
}
-base::MessageLoop*
- RenderProcessHostImpl::GetInProcessRendererThreadForTesting() {
- return g_in_process_thread;
-}
-
void RenderProcessHostImpl::ProcessDied(bool already_dead) {
// Our child process has died. If we didn't expect it, it's a crash.
// In any case, we need to let everyone know it's gone.
@@ -1661,10 +1653,11 @@ void RenderProcessHostImpl::ProcessDied(bool already_dead) {
int RenderProcessHostImpl::GetActiveViewCount() {
int num_active_views = 0;
- RenderWidgetHost::List widgets = RenderWidgetHost::GetRenderWidgetHosts();
- for (size_t i = 0; i < widgets.size(); ++i) {
+ scoped_ptr<RenderWidgetHostIterator> widgets(
+ RenderWidgetHost::GetRenderWidgetHosts());
+ while (RenderWidgetHost* widget = widgets->GetNextHost()) {
// Count only RenderWidgetHosts in this process.
- if (widgets[i]->GetProcess()->GetID() == GetID())
+ if (widget->GetProcess()->GetID() == GetID())
num_active_views++;
}
return num_active_views;
@@ -1797,17 +1790,17 @@ void RenderProcessHostImpl::OnCompositorSurfaceBuffersSwappedNoHost(
void RenderProcessHostImpl::OnGpuSwitching() {
// We are updating all widgets including swapped out ones.
- RenderWidgetHost::List widgets =
- RenderWidgetHostImpl::GetAllRenderWidgetHosts();
- for (size_t i = 0; i < widgets.size(); ++i) {
- if (!widgets[i]->IsRenderView())
+ scoped_ptr<RenderWidgetHostIterator> widgets(
+ RenderWidgetHostImpl::GetAllRenderWidgetHosts());
+ while (RenderWidgetHost* widget = widgets->GetNextHost()) {
+ if (!widget->IsRenderView())
continue;
// Skip widgets in other processes.
- if (widgets[i]->GetProcess()->GetID() != GetID())
+ if (widget->GetProcess()->GetID() != GetID())
continue;
- RenderViewHost* rvh = RenderViewHost::From(widgets[i]);
+ RenderViewHost* rvh = RenderViewHost::From(widget);
rvh->UpdateWebkitPreferences(rvh->GetWebkitPreferences());
}
}
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 72ec846303d..0e9ae1b2ad1 100644
--- a/chromium/content/browser/renderer_host/render_process_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_process_host_impl.h
@@ -33,6 +33,7 @@ class Size;
}
namespace content {
+class BrowserDemuxerAndroid;
class GpuMessageFilter;
class PeerConnectionTrackerHost;
class RendererMainThread;
@@ -177,6 +178,12 @@ class CONTENT_EXPORT RenderProcessHostImpl
static base::MessageLoop* GetInProcessRendererThreadForTesting();
+#if defined(OS_ANDROID)
+ const scoped_refptr<BrowserDemuxerAndroid>& browser_demuxer_android() {
+ return browser_demuxer_android_;
+ }
+#endif
+
protected:
// A proxy for our IPC::Channel that lives on the IO thread (see
// browser_process.h)
@@ -264,10 +271,8 @@ class CONTENT_EXPORT RenderProcessHostImpl
// This is used to clear our cache five seconds after the last use.
base::DelayTimer<RenderProcessHostImpl> cached_dibs_cleaner_;
-#if !defined(CHROME_MULTIPLE_DLL)
// Used in single-process mode.
- scoped_ptr<RendererMainThread> in_process_renderer_;
-#endif
+ scoped_ptr<base::Thread> in_process_renderer_;
// True after Init() has been called. We can't just check channel_ because we
// also reset that in the case of process termination.
@@ -324,6 +329,10 @@ class CONTENT_EXPORT RenderProcessHostImpl
// Forwards power state messages to the renderer process.
PowerMonitorMessageBroadcaster power_monitor_broadcaster_;
+#if defined(OS_ANDROID)
+ scoped_refptr<BrowserDemuxerAndroid> browser_demuxer_android_;
+#endif
+
DISALLOW_COPY_AND_ASSIGN(RenderProcessHostImpl);
};
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 87d31dca88c..81537181532 100644
--- a/chromium/content/browser/renderer_host/render_sandbox_host_linux.cc
+++ b/chromium/content/browser/renderer_host/render_sandbox_host_linux.cc
@@ -30,6 +30,8 @@
#include "content/child/webkitplatformsupport_impl.h"
#include "content/common/font_config_ipc_linux.h"
#include "content/common/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/web/WebKit.h"
#include "third_party/WebKit/public/web/linux/WebFontInfo.h"
@@ -71,6 +73,15 @@ class SandboxIPCProcess {
// positioning, so we pass the current setting through to WebKit.
WebFontInfo::setSubpixelPositioning(
gfx::GetDefaultWebkitSubpixelPositioning());
+
+ CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ command_line.AppendSwitchASCII(switches::kProcessType,
+ switches::kSandboxIPCProcess);
+
+ // Update the process title. The argv was already cached by the call to
+ // SetProcessTitleFromCommandLine in content_main_runner.cc, so we can pass
+ // NULL here (we don't have the original argv at this point).
+ SetProcessTitleFromCommandLine(NULL);
}
~SandboxIPCProcess();
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 4255d055ce1..20fec727501 100644
--- a/chromium/content/browser/renderer_host/render_view_host_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_browsertest.cc
@@ -13,7 +13,7 @@
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/content_paths.h"
#include "content/public/test/browser_test_utils.h"
-#include "content/shell/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
#include "net/base/host_port_pair.h"
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 5ce2a44d716..997452aeb54 100644
--- a/chromium/content/browser/renderer_host/render_view_host_delegate.h
+++ b/chromium/content/browser/renderer_host/render_view_host_delegate.h
@@ -50,6 +50,7 @@ class PageState;
class RenderViewHost;
class RenderViewHostDelegateView;
class SessionStorageNamespace;
+class SiteInstance;
class WebContents;
class WebContentsImpl;
struct ContextMenuParams;
@@ -58,7 +59,8 @@ struct GlobalRequestID;
struct NativeWebKeyboardEvent;
struct Referrer;
struct RendererPreferences;
-class SiteInstance;
+struct ResourceRedirectDetails;
+struct ResourceRequestDetails;
//
// RenderViewHostDelegate
@@ -151,8 +153,8 @@ class CONTENT_EXPORT RenderViewHostDelegate {
// The RenderView processed a redirect during a provisional load.
//
// TODO(creis): Remove this method and have the pre-rendering code listen to
- // the ResourceDispatcherHost's RESOURCE_RECEIVED_REDIRECT notification
- // instead. See http://crbug.com/78512.
+ // WebContentsObserver::DidGetRedirectForResourceRequest instead.
+ // See http://crbug.com/78512.
virtual void DidRedirectProvisionalLoad(
RenderViewHost* render_view_host,
int32 page_id,
@@ -164,6 +166,14 @@ class CONTENT_EXPORT RenderViewHostDelegate {
RenderViewHost* render_view_host,
const ViewHostMsg_DidFailProvisionalLoadWithError_Params& params) {}
+ // A response has been received for a resource request.
+ virtual void DidGetResourceResponseStart(
+ const ResourceRequestDetails& details) {}
+
+ // A redirect was received while requesting a resource.
+ virtual void DidGetRedirectForResourceRequest(
+ const ResourceRedirectDetails& details) {}
+
// The RenderView was navigated to a different page.
virtual void DidNavigate(RenderViewHost* render_view_host,
const ViewHostMsg_FrameNavigate_Params& params) {}
@@ -299,6 +309,7 @@ class CONTENT_EXPORT RenderViewHostDelegate {
// Notification that the renderer has become unresponsive. The
// delegate can use this notification to show a warning to the user.
virtual void RendererUnresponsive(RenderViewHost* render_view_host,
+ bool is_during_before_unload,
bool is_during_unload) {}
// Notification that a previously unresponsive renderer has become
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 20d15d38f0c..5cffd134b8e 100644
--- a/chromium/content/browser/renderer_host/render_view_host_factory.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_factory.cc
@@ -19,14 +19,15 @@ RenderViewHost* RenderViewHostFactory::Create(
RenderWidgetHostDelegate* widget_delegate,
int routing_id,
int main_frame_routing_id,
- bool swapped_out) {
+ bool swapped_out,
+ bool hidden) {
if (factory_) {
return factory_->CreateRenderViewHost(instance, delegate, widget_delegate,
routing_id, main_frame_routing_id,
swapped_out);
}
return new RenderViewHostImpl(instance, delegate, widget_delegate, routing_id,
- main_frame_routing_id, swapped_out);
+ main_frame_routing_id, swapped_out, hidden);
}
// static
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 6226187af53..b0466355d49 100644
--- a/chromium/content/browser/renderer_host/render_view_host_factory.h
+++ b/chromium/content/browser/renderer_host/render_view_host_factory.h
@@ -29,7 +29,8 @@ class RenderViewHostFactory {
RenderWidgetHostDelegate* widget_delegate,
int routing_id,
int main_frame_routing_id,
- bool swapped_out);
+ bool swapped_out,
+ bool hidden);
// Returns true if there is currently a globally-registered factory.
static bool has_factory() {
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 56801c03c18..68204fb746a 100644
--- a/chromium/content/browser/renderer_host/render_view_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_impl.cc
@@ -51,6 +51,7 @@
#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"
#include "content/public/common/content_constants.h"
@@ -72,7 +73,7 @@
#if defined(OS_MACOSX)
#include "content/browser/renderer_host/popup_menu_helper_mac.h"
#elif defined(OS_ANDROID)
-#include "media/base/android/media_player_manager.h"
+#include "content/browser/media/android/browser_media_player_manager.h"
#endif
using base::TimeDelta;
@@ -116,11 +117,7 @@ g_created_callbacks = LAZY_INSTANCE_INITIALIZER;
// static
RenderViewHost* RenderViewHost::FromID(int render_process_id,
int render_view_id) {
- RenderWidgetHost* widget =
- RenderWidgetHost::FromID(render_process_id, render_view_id);
- if (!widget || !widget->IsRenderView())
- return NULL;
- return static_cast<RenderViewHostImpl*>(RenderWidgetHostImpl::From(widget));
+ return RenderViewHostImpl::FromID(render_process_id, render_view_id);
}
// static
@@ -143,8 +140,11 @@ void RenderViewHost::FilterURL(const RenderProcessHost* process,
// static
RenderViewHostImpl* RenderViewHostImpl::FromID(int render_process_id,
int render_view_id) {
- return static_cast<RenderViewHostImpl*>(
- RenderViewHost::FromID(render_process_id, render_view_id));
+ RenderWidgetHost* widget =
+ RenderWidgetHost::FromID(render_process_id, render_view_id);
+ if (!widget || !widget->IsRenderView())
+ return NULL;
+ return static_cast<RenderViewHostImpl*>(RenderWidgetHostImpl::From(widget));
}
RenderViewHostImpl::RenderViewHostImpl(
@@ -153,8 +153,12 @@ RenderViewHostImpl::RenderViewHostImpl(
RenderWidgetHostDelegate* widget_delegate,
int routing_id,
int main_frame_routing_id,
- bool swapped_out)
- : RenderWidgetHostImpl(widget_delegate, instance->GetProcess(), routing_id),
+ bool swapped_out,
+ bool hidden)
+ : RenderWidgetHostImpl(widget_delegate,
+ instance->GetProcess(),
+ routing_id,
+ hidden),
delegate_(delegate),
instance_(static_cast<SiteInstanceImpl*>(instance)),
waiting_for_drag_context_response_(false),
@@ -191,7 +195,7 @@ RenderViewHostImpl::RenderViewHostImpl(
instance_->increment_active_view_count();
#if defined(OS_ANDROID)
- media_player_manager_ = media::MediaPlayerManager::Create(this);
+ media_player_manager_ = BrowserMediaPlayerManager::Create(this);
#endif
}
@@ -259,6 +263,7 @@ bool RenderViewHostImpl::CreateRenderView(
// Ensure the RenderView sets its opener correctly.
params.opener_route_id = opener_route_id;
params.swapped_out = is_swapped_out_;
+ params.hidden = is_hidden();
params.next_page_id = next_page_id;
GetWebScreenInfo(&params.screen_info);
params.accessibility_mode = accessibility_mode();
@@ -338,7 +343,7 @@ void RenderViewHostImpl::Navigate(const ViewMsg_Navigate_Params& params) {
//
// WebKit doesn't send throb notifications for JavaScript URLs, so we
// don't want to either.
- if (!params.url.SchemeIs(chrome::kJavaScriptScheme))
+ if (!params.url.SchemeIs(kJavaScriptScheme))
delegate_->DidStartLoading(this);
FOR_EACH_OBSERVER(RenderViewHostObserver, observers_, Navigate(params.url));
@@ -479,9 +484,10 @@ void RenderViewHostImpl::WasSwappedOut() {
// Count the number of active widget hosts for the process, which
// is equivalent to views using the process as of this writing.
- RenderWidgetHost::List widgets = RenderWidgetHost::GetRenderWidgetHosts();
- for (size_t i = 0; i < widgets.size(); ++i) {
- if (widgets[i]->GetProcess()->GetID() == GetProcess()->GetID())
+ scoped_ptr<RenderWidgetHostIterator> widgets(
+ RenderWidgetHost::GetRenderWidgetHosts());
+ while (RenderWidgetHost* widget = widgets->GetNextHost()) {
+ if (widget->GetProcess()->GetID() == GetProcess()->GetID())
++views;
}
@@ -736,7 +742,8 @@ void RenderViewHostImpl::JavaScriptDialogClosed(IPC::Message* reply_msg,
// This must be done after sending the reply since RenderView can't close
// correctly while waiting for a response.
if (is_waiting && are_javascript_messages_suppressed_)
- delegate_->RendererUnresponsive(this, is_waiting);
+ delegate_->RendererUnresponsive(
+ this, is_waiting_for_beforeunload_ack_, is_waiting_for_unload_ack_);
}
void RenderViewHostImpl::DragSourceEndedAt(
@@ -763,6 +770,12 @@ void RenderViewHostImpl::DragSourceSystemDragEnded() {
}
void RenderViewHostImpl::AllowBindings(int bindings_flags) {
+ // Never grant any bindings to browser plugin guests.
+ if (GetProcess()->IsGuest()) {
+ NOTREACHED() << "Never grant bindings to a guest process.";
+ return;
+ }
+
// Ensure we aren't granting WebUI bindings to a process that has already
// been used for non-privileged views.
if (bindings_flags & BINDINGS_POLICY_WEB_UI &&
@@ -777,12 +790,6 @@ void RenderViewHostImpl::AllowBindings(int bindings_flags) {
return;
}
- // Never grant any bindings to browser plugin guests.
- if (GetProcess()->IsGuest()) {
- NOTREACHED() << "Never grant bindings to a guest process.";
- return;
- }
-
if (bindings_flags & BINDINGS_POLICY_WEB_UI) {
ChildProcessSecurityPolicyImpl::GetInstance()->GrantWebUIBindings(
GetProcess()->GetID());
@@ -999,8 +1006,7 @@ bool RenderViewHostImpl::OnMessageReceived(const IPC::Message& msg) {
OnDidAccessInitialDocument)
IPC_MESSAGE_HANDLER(ViewHostMsg_DomOperationResponse,
OnDomOperationResponse)
- IPC_MESSAGE_HANDLER(AccessibilityHostMsg_Notifications,
- OnAccessibilityNotifications)
+ IPC_MESSAGE_HANDLER(AccessibilityHostMsg_Events, OnAccessibilityEvents)
// Have the super handle all other messages.
IPC_MESSAGE_UNHANDLED(
handled = RenderWidgetHostImpl::OnMessageReceived(msg))
@@ -1016,6 +1022,11 @@ bool RenderViewHostImpl::OnMessageReceived(const IPC::Message& msg) {
return handled;
}
+void RenderViewHostImpl::Init() {
+ RenderWidgetHostImpl::Init();
+ main_render_frame_host()->Init();
+}
+
void RenderViewHostImpl::Shutdown() {
// If we are being run modally (see RunModal), then we need to cleanup.
if (run_modal_reply_msg_) {
@@ -1239,8 +1250,6 @@ void RenderViewHostImpl::OnNavigate(const IPC::Message& msg) {
FilterURL(policy, process, false, &(*it));
}
FilterURL(policy, process, true, &validated_params.searchable_form_url);
- FilterURL(policy, process, true, &validated_params.password_form.origin);
- FilterURL(policy, process, true, &validated_params.password_form.action);
// Without this check, the renderer can trick the browser into using
// filenames it can't access in a future session restore.
@@ -1354,6 +1363,8 @@ void RenderViewHostImpl::OnContextMenu(const ContextMenuParams& params) {
void RenderViewHostImpl::OnToggleFullscreen(bool enter_fullscreen) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
delegate_->ToggleFullscreenMode(enter_fullscreen);
+ // We need to notify the contents that its fullscreen state has changed. This
+ // is done as part of the resize message.
WasResized();
}
@@ -1399,7 +1410,7 @@ void RenderViewHostImpl::OnDidChangeNumWheelEvents(int count) {
void RenderViewHostImpl::OnSelectionChanged(const string16& text,
size_t offset,
- const ui::Range& range) {
+ const gfx::Range& range) {
if (view_)
view_->SelectionChanged(text, offset, range);
}
@@ -1464,7 +1475,7 @@ void RenderViewHostImpl::OnStartDragging(
ChildProcessSecurityPolicyImpl::GetInstance();
// Allow drag of Javascript URLs to enable bookmarklet drag to bookmark bar.
- if (!filtered_data.url.SchemeIs(chrome::kJavaScriptScheme))
+ if (!filtered_data.url.SchemeIs(kJavaScriptScheme))
FilterURL(policy, process, true, &filtered_data.url);
FilterURL(policy, process, false, &filtered_data.html_base_url);
// Filter out any paths that the renderer didn't have access to. This prevents
@@ -1522,6 +1533,7 @@ void RenderViewHostImpl::OnAddMessageToConsole(
const string16& source_id) {
if (delegate_->AddMessageToConsole(level, message, line_no, source_id))
return;
+
// Pass through log level only on WebUI pages to limit console spew.
int32 resolved_level = HasWebUIScheme(delegate_->GetURL()) ? level : 0;
@@ -1595,7 +1607,7 @@ void RenderViewHostImpl::OnClosePageACK() {
void RenderViewHostImpl::NotifyRendererUnresponsive() {
delegate_->RendererUnresponsive(
- this, is_waiting_for_beforeunload_ack_ || is_waiting_for_unload_ack_);
+ this, is_waiting_for_beforeunload_ack_, is_waiting_for_unload_ack_);
}
void RenderViewHostImpl::NotifyRendererResponsive() {
@@ -1772,9 +1784,8 @@ void RenderViewHostImpl::SetAltErrorPageURL(const GURL& url) {
void RenderViewHostImpl::ExitFullscreen() {
RejectMouseLockOrUnlockIfNecessary();
- // We need to notify the contents that its fullscreen state has changed. This
- // is done as part of the resize message.
- WasResized();
+ // Notify delegate_ and renderer of fullscreen state change.
+ OnToggleFullscreen(false);
}
WebPreferences RenderViewHostImpl::GetWebkitPreferences() {
@@ -1789,7 +1800,7 @@ void RenderViewHostImpl::DisownOpener() {
}
void RenderViewHostImpl::SetAccessibilityCallbackForTesting(
- const base::Callback<void(AccessibilityNotification)>& callback) {
+ const base::Callback<void(WebKit::WebAXEvent)>& callback) {
accessibility_testing_callback_ = callback;
}
@@ -1871,10 +1882,6 @@ void RenderViewHostImpl::ExecutePluginActionAtLocation(
Send(new ViewMsg_PluginActionAt(GetRoutingID(), location, action));
}
-void RenderViewHostImpl::DisassociateFromPopupCount() {
- Send(new ViewMsg_DisassociateFromPopupCount(GetRoutingID()));
-}
-
void RenderViewHostImpl::NotifyMoveOrResizeStarted() {
Send(new ViewMsg_MoveOrResizeStarted(GetRoutingID()));
}
@@ -1883,13 +1890,13 @@ void RenderViewHostImpl::StopFinding(StopFindAction action) {
Send(new ViewMsg_StopFinding(GetRoutingID(), action));
}
-void RenderViewHostImpl::OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>& params) {
+void RenderViewHostImpl::OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>& params) {
if (view_ && !is_swapped_out_)
- view_->OnAccessibilityNotifications(params);
+ view_->OnAccessibilityEvents(params);
// Always send an ACK or the renderer can be in a bad state.
- Send(new AccessibilityMsg_Notifications_ACK(GetRoutingID()));
+ Send(new AccessibilityMsg_Events_ACK(GetRoutingID()));
// The rest of this code is just for testing; bail out if we're not
// in that mode.
@@ -1897,10 +1904,10 @@ void RenderViewHostImpl::OnAccessibilityNotifications(
return;
for (unsigned i = 0; i < params.size(); i++) {
- const AccessibilityHostMsg_NotificationParams& param = params[i];
- AccessibilityNotification src_type = param.notification_type;
- if (src_type == AccessibilityNotificationLayoutComplete ||
- src_type == AccessibilityNotificationLoadComplete) {
+ const AccessibilityHostMsg_EventParams& param = params[i];
+ WebKit::WebAXEvent src_type = param.event_type;
+ if (src_type == WebKit::WebAXEventLayoutComplete ||
+ src_type == WebKit::WebAXEventLoadComplete) {
MakeAccessibilityNodeDataTree(param.nodes, &accessibility_tree_);
}
accessibility_testing_callback_.Run(src_type);
@@ -1953,7 +1960,7 @@ void RenderViewHostImpl::OnShowDesktopNotification(
// allows unwanted cross-domain access.
GURL url = params.contents_url;
if (params.is_html &&
- (url.SchemeIs(chrome::kJavaScriptScheme) ||
+ (url.SchemeIs(kJavaScriptScheme) ||
url.SchemeIs(chrome::kFileScheme))) {
return;
}
@@ -2024,6 +2031,11 @@ 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.
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 20caaf5ea73..c4bfb7876d1 100644
--- a/chromium/content/browser/renderer_host/render_view_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_view_host_impl.h
@@ -18,22 +18,22 @@
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/site_instance_impl.h"
#include "content/common/accessibility_node_data.h"
-#include "content/common/accessibility_notification.h"
#include "content/common/drag_event_source_info.h"
#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/window_container_type.h"
#include "net/base/load_states.h"
-#include "third_party/skia/include/core/SkColor.h"
+#include "third_party/WebKit/public/web/WebAXEnums.h"
#include "third_party/WebKit/public/web/WebConsoleMessage.h"
#include "third_party/WebKit/public/web/WebPopupType.h"
#include "third_party/WebKit/public/web/WebTextDirection.h"
+#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/window_open_disposition.h"
class SkBitmap;
class ViewMsg_Navigate;
-struct AccessibilityHostMsg_NotificationParams;
+struct AccessibilityHostMsg_EventParams;
struct MediaPlayerAction;
struct ViewHostMsg_CreateWindow_Params;
struct ViewHostMsg_DidFailProvisionalLoadWithError_Params;
@@ -48,19 +48,17 @@ namespace base {
class ListValue;
}
-namespace ui {
+namespace gfx {
class Range;
-struct SelectedFileInfo;
}
-#if defined(OS_ANDROID)
-namespace media {
-class MediaPlayerManager;
+namespace ui {
+struct SelectedFileInfo;
}
-#endif
namespace content {
+class BrowserMediaPlayerManager;
class ChildProcessSecurityPolicyImpl;
class PageState;
class RenderFrameHostImpl;
@@ -110,7 +108,8 @@ class CONTENT_EXPORT RenderViewHostImpl
// |routing_id| could be a valid route id, or it could be MSG_ROUTING_NONE, in
// which case RenderWidgetHost will create a new one. |swapped_out| indicates
// whether the view should initially be swapped out (e.g., for an opener
- // frame being rendered by another process).
+ // frame being rendered by another process). |hidden| indicates whether the
+ // view is initially hidden or visible.
//
// The |session_storage_namespace| parameter allows multiple render views and
// WebContentses to share the same session storage (part of the WebStorage
@@ -123,7 +122,8 @@ class CONTENT_EXPORT RenderViewHostImpl
RenderWidgetHostDelegate* widget_delegate,
int routing_id,
int main_frame_routing_id,
- bool swapped_out);
+ bool swapped_out,
+ bool hidden);
virtual ~RenderViewHostImpl();
// RenderViewHost implementation.
@@ -131,7 +131,6 @@ class CONTENT_EXPORT RenderViewHostImpl
virtual void ClearFocusedNode() OVERRIDE;
virtual void ClosePage() OVERRIDE;
virtual void CopyImageAt(int x, int y) OVERRIDE;
- virtual void DisassociateFromPopupCount() OVERRIDE;
virtual void DesktopNotificationPermissionRequestDone(
int callback_context) OVERRIDE;
virtual void DesktopNotificationPostDisplay(int callback_context) OVERRIDE;
@@ -354,6 +353,7 @@ class CONTENT_EXPORT RenderViewHostImpl
}
// RenderWidgetHost public overrides.
+ virtual void Init() OVERRIDE;
virtual void Shutdown() OVERRIDE;
virtual bool IsRenderView() const OVERRIDE;
virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
@@ -388,7 +388,7 @@ class CONTENT_EXPORT RenderViewHostImpl
#endif
#if defined(OS_ANDROID)
- media::MediaPlayerManager* media_player_manager() {
+ BrowserMediaPlayerManager* media_player_manager() {
return media_player_manager_;
}
@@ -417,7 +417,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(AccessibilityNotification)>& callback);
+ const base::Callback<void(WebKit::WebAXEvent)>& callback);
// Only valid if SetAccessibilityCallbackForTesting was called and
// the callback was run at least once. Returns a snapshot of the
@@ -526,7 +526,7 @@ class CONTENT_EXPORT RenderViewHostImpl
void OnDidChangeNumWheelEvents(int count);
void OnSelectionChanged(const string16& text,
size_t offset,
- const ui::Range& range);
+ const gfx::Range& range);
void OnSelectionBoundsChanged(
const ViewHostMsg_SelectionBounds_Params& params);
void OnPasteFromSelectionClipboard();
@@ -562,8 +562,8 @@ class CONTENT_EXPORT RenderViewHostImpl
const base::TimeTicks& renderer_before_unload_end_time);
void OnClosePageACK();
void OnSwapOutACK();
- void OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>& params);
+ void OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>& params);
void OnScriptEvalResponse(int id, const base::ListValue& result);
void OnDidZoomURL(double zoom_level, bool remember, const GURL& url);
void OnRequestDesktopNotificationPermission(const GURL& origin,
@@ -584,6 +584,11 @@ class CONTENT_EXPORT RenderViewHostImpl
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.
@@ -678,8 +683,7 @@ class CONTENT_EXPORT RenderViewHostImpl
std::map<int, JavascriptResultCallback> javascript_callbacks_;
// Accessibility callback for testing.
- base::Callback<void(AccessibilityNotification)>
- accessibility_testing_callback_;
+ base::Callback<void(WebKit::WebAXEvent)> accessibility_testing_callback_;
// The most recently received accessibility tree - for testing only.
AccessibilityNodeDataTreeNode accessibility_tree_;
@@ -699,7 +703,7 @@ class CONTENT_EXPORT RenderViewHostImpl
#if defined(OS_ANDROID)
// Manages all the android mediaplayer objects and handling IPCs for video.
// This class inherits from RenderViewHostObserver.
- media::MediaPlayerManager* media_player_manager_;
+ BrowserMediaPlayerManager* media_player_manager_;
#endif
DISALLOW_COPY_AND_ASSIGN(RenderViewHostImpl);
diff --git a/chromium/content/browser/renderer_host/render_view_host_manager_browsertest.cc b/chromium/content/browser/renderer_host/render_view_host_manager_browsertest.cc
index 4053d6593f2..55785d07859 100644
--- a/chromium/content/browser/renderer_host/render_view_host_manager_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_manager_browsertest.cc
@@ -25,7 +25,7 @@
#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/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
#include "net/base/net_util.h"
@@ -86,7 +86,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// Wait for the navigation in the new window to finish, if it hasn't.
WaitForLoadStop(new_shell->web_contents());
EXPECT_EQ("/files/navigate_opener.html",
- new_shell->web_contents()->GetURL().path());
+ new_shell->web_contents()->GetLastCommittedURL().path());
// Should have the same SiteInstance.
scoped_refptr<SiteInstance> blank_site_instance(
@@ -153,7 +153,8 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// Wait for the window to open.
Shell* new_shell = new_shell_observer.GetShell();
- EXPECT_EQ("/files/title2.html", new_shell->web_contents()->GetURL().path());
+ EXPECT_EQ("/files/title2.html",
+ new_shell->web_contents()->GetVisibleURL().path());
// Wait for the cross-site transition in the new tab to finish.
WaitForLoadStop(new_shell->web_contents());
@@ -207,7 +208,8 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
Shell* new_shell = new_shell_observer.GetShell();
// Opens in new window.
- EXPECT_EQ("/files/title2.html", new_shell->web_contents()->GetURL().path());
+ EXPECT_EQ("/files/title2.html",
+ new_shell->web_contents()->GetVisibleURL().path());
// Wait for the cross-site transition in the new tab to finish.
WaitForLoadStop(new_shell->web_contents());
@@ -262,7 +264,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// Wait for the cross-site transition in the new tab to finish.
WaitForLoadStop(new_shell->web_contents());
EXPECT_EQ("/files/title2.html",
- new_shell->web_contents()->GetURL().path());
+ new_shell->web_contents()->GetLastCommittedURL().path());
// Should have the same SiteInstance.
scoped_refptr<SiteInstance> blank_site_instance(
@@ -308,7 +310,8 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// Opens in same window.
EXPECT_EQ(1u, Shell::windows().size());
- EXPECT_EQ("/files/title2.html", shell()->web_contents()->GetURL().path());
+ EXPECT_EQ("/files/title2.html",
+ shell()->web_contents()->GetLastCommittedURL().path());
// Should have the same SiteInstance.
scoped_refptr<SiteInstance> noref_site_instance(
@@ -376,7 +379,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// Wait for the navigation in the new tab to finish, if it hasn't.
WaitForLoadStop(new_shell->web_contents());
EXPECT_EQ("/files/navigate_opener.html",
- new_shell->web_contents()->GetURL().path());
+ new_shell->web_contents()->GetLastCommittedURL().path());
// Should have the same SiteInstance.
scoped_refptr<SiteInstance> blank_site_instance(
@@ -421,7 +424,13 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// Test that setting the opener to null in a window affects cross-process
// navigations, including those to existing entries. http://crbug.com/156669.
-IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, DisownOpener) {
+// Flaky on windows: http://crbug.com/291249
+#if defined(OS_WIN)
+#define MAYBE_DisownOpener DISABLED_DisownOpener
+#else
+#define MAYBE_DisownOpener DisownOpener
+#endif
+IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, MAYBE_DisownOpener) {
// Start two servers with different sites.
ASSERT_TRUE(test_server()->Start());
net::SpawnedTestServer https_server(
@@ -456,7 +465,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, DisownOpener) {
// Wait for the navigation in the new tab to finish, if it hasn't.
WaitForLoadStop(new_shell->web_contents());
EXPECT_EQ("/files/title2.html",
- new_shell->web_contents()->GetURL().path());
+ new_shell->web_contents()->GetLastCommittedURL().path());
// Should have the same SiteInstance.
scoped_refptr<SiteInstance> blank_site_instance(
@@ -562,7 +571,8 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// 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->GetURL().path());
+ 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());
@@ -581,7 +591,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
Shell* new_shell2 = new_shell_observer2.GetShell();
WebContents* new_contents = new_shell2->web_contents();
WaitForLoadStop(new_contents);
- EXPECT_EQ("/files/title2.html", new_contents->GetURL().path());
+ 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 =
@@ -698,7 +708,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// Wait for the navigation in the new window to finish, if it hasn't.
WaitForLoadStop(new_shell->web_contents());
EXPECT_EQ("/files/navigate_opener.html",
- new_shell->web_contents()->GetURL().path());
+ new_shell->web_contents()->GetLastCommittedURL().path());
// Should have the same SiteInstance.
scoped_refptr<SiteInstance> blank_site_instance(
@@ -765,7 +775,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// Wait for the navigation in the new window to finish, if it hasn't.
WaitForLoadStop(new_shell->web_contents());
EXPECT_EQ("/files/navigate_opener.html",
- new_shell->web_contents()->GetURL().path());
+ new_shell->web_contents()->GetLastCommittedURL().path());
// Should have the same SiteInstance.
scoped_refptr<SiteInstance> opened_site_instance(
@@ -829,7 +839,8 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, ClickLinkAfter204Error) {
scoped_refptr<SiteInstance> post_nav_site_instance(
shell()->web_contents()->GetSiteInstance());
EXPECT_EQ(orig_site_instance, post_nav_site_instance);
- EXPECT_EQ("/nocontent", shell()->web_contents()->GetURL().path());
+ EXPECT_EQ("/nocontent",
+ shell()->web_contents()->GetVisibleURL().path());
EXPECT_EQ("/files/click-noreferrer-links.html",
shell()->web_contents()->GetController().
GetLastCommittedEntry()->GetVirtualURL().path());
@@ -847,7 +858,8 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, ClickLinkAfter204Error) {
// Opens in same tab.
EXPECT_EQ(1u, Shell::windows().size());
- EXPECT_EQ("/files/title2.html", shell()->web_contents()->GetURL().path());
+ EXPECT_EQ("/files/title2.html",
+ shell()->web_contents()->GetLastCommittedURL().path());
// Should have the same SiteInstance.
scoped_refptr<SiteInstance> noref_site_instance(
@@ -1073,7 +1085,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// Wait for the navigation in the new tab to finish, if it hasn't.
WaitForLoadStop(new_shell->web_contents());
EXPECT_EQ("/files/navigate_opener.html",
- new_shell->web_contents()->GetURL().path());
+ new_shell->web_contents()->GetLastCommittedURL().path());
RenderViewHost* rvh = new_shell->web_contents()->GetRenderViewHost();
@@ -1104,7 +1116,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
}
EXPECT_EQ("/files/navigate_opener.html",
- new_shell->web_contents()->GetURL().path());
+ new_shell->web_contents()->GetLastCommittedURL().path());
EXPECT_EQ(rvh, new_shell->web_contents()->GetRenderViewHost());
@@ -1187,7 +1199,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, LeakingRenderViewHosts) {
// view-source URL, we create a new SiteInstance.
RenderViewHost* blank_rvh = shell()->web_contents()->GetRenderViewHost();
SiteInstance* blank_site_instance = blank_rvh->GetSiteInstance();
- EXPECT_EQ(shell()->web_contents()->GetURL(), GURL::EmptyGURL());
+ EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), GURL::EmptyGURL());
EXPECT_EQ(blank_site_instance->GetSiteURL(), GURL::EmptyGURL());
rvh_observers.AddObserverToRVH(blank_rvh);
@@ -1269,7 +1281,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// Wait for the navigation in the new window to finish, if it hasn't.
WaitForLoadStop(new_shell->web_contents());
EXPECT_EQ("/files/title1.html",
- new_shell->web_contents()->GetURL().path());
+ new_shell->web_contents()->GetLastCommittedURL().path());
// Should have the same SiteInstance.
EXPECT_EQ(orig_site_instance, new_shell->web_contents()->GetSiteInstance());
@@ -1286,7 +1298,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// Make sure it ends up at the right page.
WaitForLoadStop(shell()->web_contents());
EXPECT_EQ(https_server.GetURL("files/title1.html"),
- shell()->web_contents()->GetURL());
+ shell()->web_contents()->GetLastCommittedURL());
EXPECT_EQ(new_site_instance, shell()->web_contents()->GetSiteInstance());
}
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 a38e0446f3d..f4d694fae42 100644
--- a/chromium/content/browser/renderer_host/render_view_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_unittest.cc
@@ -288,4 +288,11 @@ TEST_F(RenderViewHostTest, NavigationWithBadHistoryItemFiles) {
EXPECT_EQ(1, process()->bad_msg_count());
}
+TEST_F(RenderViewHostTest, RoutingIdSane) {
+ EXPECT_EQ(test_rvh()->GetProcess(),
+ test_rvh()->main_render_frame_host()->GetProcess());
+ EXPECT_NE(test_rvh()->GetRoutingID(),
+ test_rvh()->main_render_frame_host()->routing_id());
+}
+
} // namespace content
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 9f11299b1a6..bfdf6a5450a 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_browsertest.cc
@@ -7,7 +7,7 @@
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_paths.h"
-#include "content/shell/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
#include "net/base/net_util.h"
@@ -46,8 +46,14 @@ class RenderWidgetHostBrowserTest : public ContentBrowserTest {
base::FilePath test_dir_;
};
+// Disabled on Windows and CrOS because it is flaky: crbug.com/272379.
+#if defined(OS_WIN) || defined(OS_CHROMEOS)
+#define MAYBE_GetSnapshotFromRendererTest DISABLED_GetSnapshotFromRendererTest
+#else
+#define MAYBE_GetSnapshotFromRendererTest GetSnapshotFromRendererTest
+#endif
IN_PROC_BROWSER_TEST_F(RenderWidgetHostBrowserTest,
- GetSnapshotFromRendererTest) {
+ MAYBE_GetSnapshotFromRendererTest) {
base::RunLoop run_loop;
NavigateToURL(shell(), GURL(net::FilePathToFileURL(
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 edd21fe5987..4fce8d8cb2d 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_impl.cc
@@ -22,12 +22,14 @@
#include "cc/output/compositor_frame.h"
#include "cc/output/compositor_frame_ack.h"
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
+#include "content/browser/gpu/compositor_util.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/gpu/gpu_process_host_ui_shim.h"
#include "content/browser/gpu/gpu_surface_tracker.h"
#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/overscroll_controller.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
@@ -40,10 +42,10 @@
#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
#include "content/port/browser/render_widget_host_view_port.h"
-#include "content/public/browser/compositor_util.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
+#include "content/public/browser/render_widget_host_iterator.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
@@ -51,8 +53,8 @@
#include "skia/ext/image_operations.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
-#include "ui/base/events/event.h"
-#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/events/event.h"
+#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/size_conversions.h"
#include "ui/gfx/skbitmap_operations.h"
#include "ui/gfx/vector2d_conversions.h"
@@ -91,15 +93,50 @@ const int kPaintMsgTimeoutMS = 50;
base::LazyInstance<std::vector<RenderWidgetHost::CreatedCallback> >
g_created_callbacks = LAZY_INSTANCE_INITIALIZER;
-} // namespace
-
-
typedef std::pair<int32, int32> RenderWidgetHostID;
typedef base::hash_map<RenderWidgetHostID, RenderWidgetHostImpl*>
RoutingIDWidgetMap;
-static base::LazyInstance<RoutingIDWidgetMap> g_routing_id_widget_map =
+base::LazyInstance<RoutingIDWidgetMap> g_routing_id_widget_map =
LAZY_INSTANCE_INITIALIZER;
+// Implements the RenderWidgetHostIterator interface. It keeps a list of
+// RenderWidgetHosts, and makes sure it returns a live RenderWidgetHost at each
+// iteration (or NULL if there isn't any left).
+class RenderWidgetHostIteratorImpl : public RenderWidgetHostIterator {
+ public:
+ RenderWidgetHostIteratorImpl()
+ : current_index_(0) {
+ }
+
+ virtual ~RenderWidgetHostIteratorImpl() {
+ }
+
+ void Add(RenderWidgetHost* host) {
+ hosts_.push_back(RenderWidgetHostID(host->GetProcess()->GetID(),
+ host->GetRoutingID()));
+ }
+
+ // RenderWidgetHostIterator:
+ virtual RenderWidgetHost* GetNextHost() OVERRIDE {
+ RenderWidgetHost* host = NULL;
+ while (current_index_ < hosts_.size() && !host) {
+ RenderWidgetHostID id = hosts_[current_index_];
+ host = RenderWidgetHost::FromID(id.first, id.second);
+ ++current_index_;
+ }
+ return host;
+ }
+
+ private:
+ std::vector<RenderWidgetHostID> hosts_;
+ size_t current_index_;
+
+ DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostIteratorImpl);
+};
+
+} // namespace
+
+
// static
void RenderWidgetHost::RemoveAllBackingStores() {
BackingStoreManager::RemoveAllBackingStores();
@@ -115,7 +152,8 @@ size_t RenderWidgetHost::BackingStoreMemorySize() {
RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
RenderProcessHost* process,
- int routing_id)
+ int routing_id,
+ bool hidden)
: view_(NULL),
renderer_initialized_(false),
hung_renderer_delay_ms_(kHungRendererDelayMs),
@@ -124,11 +162,12 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
routing_id_(routing_id),
surface_id_(0),
is_loading_(false),
- is_hidden_(false),
+ is_hidden_(hidden),
is_fullscreen_(false),
is_accelerated_compositing_active_(false),
repaint_ack_pending_(false),
resize_ack_pending_(false),
+ screen_info_out_of_date_(false),
overdraw_bottom_height_(0.f),
should_auto_resize_(false),
waiting_for_screen_rects_ack_(false),
@@ -175,9 +214,11 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
g_routing_id_widget_map.Get().insert(std::make_pair(
RenderWidgetHostID(process->GetID(), routing_id_), this));
process_->AddRoute(routing_id_, this);
- // Because the widget initializes as is_hidden_ == false,
- // tell the process host that we're alive.
- process_->WidgetRestored();
+
+ // If we're initially visible, tell the process host that we're alive.
+ // Otherwise we'll notify the process host when we are first shown.
+ if (!hidden)
+ process_->WidgetRestored();
accessibility_mode_ =
BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode();
@@ -185,7 +226,8 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
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, routing_id_));
+ input_router_.reset(
+ new ImmediateInputRouter(process_, this, this, routing_id_));
#if defined(USE_AURA)
bool overscroll_enabled = CommandLine::ForCurrentProcess()->
@@ -222,6 +264,7 @@ RenderWidgetHost* RenderWidgetHost::FromID(
RenderWidgetHostImpl* RenderWidgetHostImpl::FromID(
int32 process_id,
int32 routing_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
RoutingIDWidgetMap* widgets = g_routing_id_widget_map.Pointer();
RoutingIDWidgetMap::iterator it = widgets->find(
RenderWidgetHostID(process_id, routing_id));
@@ -229,8 +272,8 @@ RenderWidgetHostImpl* RenderWidgetHostImpl::FromID(
}
// static
-std::vector<RenderWidgetHost*> RenderWidgetHost::GetRenderWidgetHosts() {
- std::vector<RenderWidgetHost*> hosts;
+scoped_ptr<RenderWidgetHostIterator> RenderWidgetHost::GetRenderWidgetHosts() {
+ RenderWidgetHostIteratorImpl* hosts = new RenderWidgetHostIteratorImpl();
RoutingIDWidgetMap* widgets = g_routing_id_widget_map.Pointer();
for (RoutingIDWidgetMap::const_iterator it = widgets->begin();
it != widgets->end();
@@ -238,28 +281,31 @@ std::vector<RenderWidgetHost*> RenderWidgetHost::GetRenderWidgetHosts() {
RenderWidgetHost* widget = it->second;
if (!widget->IsRenderView()) {
- hosts.push_back(widget);
+ hosts->Add(widget);
continue;
}
// Add only active RenderViewHosts.
RenderViewHost* rvh = RenderViewHost::From(widget);
if (!static_cast<RenderViewHostImpl*>(rvh)->is_swapped_out())
- hosts.push_back(widget);
+ hosts->Add(widget);
}
- return hosts;
+
+ return scoped_ptr<RenderWidgetHostIterator>(hosts);
}
// static
-std::vector<RenderWidgetHost*> RenderWidgetHostImpl::GetAllRenderWidgetHosts() {
- std::vector<RenderWidgetHost*> hosts;
+scoped_ptr<RenderWidgetHostIterator>
+RenderWidgetHostImpl::GetAllRenderWidgetHosts() {
+ RenderWidgetHostIteratorImpl* hosts = new RenderWidgetHostIteratorImpl();
RoutingIDWidgetMap* widgets = g_routing_id_widget_map.Pointer();
for (RoutingIDWidgetMap::const_iterator it = widgets->begin();
it != widgets->end();
++it) {
- hosts.push_back(it->second);
+ hosts->Add(it->second);
}
- return hosts;
+
+ return scoped_ptr<RenderWidgetHostIterator>(hosts);
}
// static
@@ -358,8 +404,8 @@ void RenderWidgetHostImpl::SendScreenRects() {
}
base::TimeDelta
- RenderWidgetHostImpl::GetSyntheticScrollMessageInterval() const {
- return smooth_scroll_gesture_controller_.GetSyntheticScrollMessageInterval();
+ RenderWidgetHostImpl::GetSyntheticGestureMessageInterval() const {
+ return synthetic_gesture_controller_.GetSyntheticGestureMessageInterval();
}
void RenderWidgetHostImpl::SetOverscrollControllerEnabled(bool enabled) {
@@ -430,6 +476,7 @@ bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
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)
@@ -473,12 +520,15 @@ bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
bool RenderWidgetHostImpl::Send(IPC::Message* msg) {
if (IPC_MESSAGE_ID_CLASS(msg->type()) == InputMsgStart)
- return input_router_->SendInput(msg);
+ return input_router_->SendInput(make_scoped_ptr(msg));
return process_->Send(msg);
}
void RenderWidgetHostImpl::WasHidden() {
+ if (is_hidden_)
+ return;
+
is_hidden_ = true;
// Don't bother reporting hung state when we aren't active.
@@ -499,7 +549,6 @@ void RenderWidgetHostImpl::WasHidden() {
}
void RenderWidgetHostImpl::WasShown() {
- // When we create the widget, it is created as *not* hidden.
if (!is_hidden_)
return;
is_hidden_ = false;
@@ -548,8 +597,10 @@ void RenderWidgetHostImpl::WasShown() {
}
void RenderWidgetHostImpl::WasResized() {
+ // Skip if the |delegate_| has already been detached because
+ // it's web contents is being deleted.
if (resize_ack_pending_ || !process_->HasConnection() || !view_ ||
- !renderer_initialized_ || should_auto_resize_) {
+ !renderer_initialized_ || should_auto_resize_ || !delegate_) {
return;
}
@@ -565,7 +616,7 @@ void RenderWidgetHostImpl::WasResized() {
bool size_changed = new_size != last_requested_size_;
bool side_payload_changed =
- !screen_info_.get() ||
+ screen_info_out_of_date_ ||
old_physical_backing_size != physical_backing_size_ ||
was_fullscreen != is_fullscreen_ ||
old_overdraw_bottom_height != overdraw_bottom_height_;
@@ -838,20 +889,20 @@ void RenderWidgetHostImpl::DonePaintingToBackingStore() {
Send(new ViewMsg_UpdateRect_ACK(GetRoutingID()));
}
-void RenderWidgetHostImpl::ScheduleComposite() {
+bool RenderWidgetHostImpl::ScheduleComposite() {
if (is_hidden_ || !is_accelerated_compositing_active_ ||
- current_size_.IsEmpty()) {
- return;
+ current_size_.IsEmpty() || repaint_ack_pending_ ||
+ resize_ack_pending_ || view_being_painted_) {
+ return false;
}
// Send out a request to the renderer to paint the view if required.
- if (!repaint_ack_pending_ && !resize_ack_pending_ && !view_being_painted_) {
- repaint_start_time_ = TimeTicks::Now();
- repaint_ack_pending_ = true;
- TRACE_EVENT_ASYNC_BEGIN0(
- "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
- Send(new ViewMsg_Repaint(routing_id_, current_size_));
- }
+ repaint_start_time_ = TimeTicks::Now();
+ repaint_ack_pending_ = true;
+ TRACE_EVENT_ASYNC_BEGIN0(
+ "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
+ Send(new ViewMsg_Repaint(routing_id_, current_size_));
+ return true;
}
void RenderWidgetHostImpl::StartHangMonitorTimeout(TimeDelta delay) {
@@ -1010,6 +1061,12 @@ void RenderWidgetHostImpl::ForwardMouseEventWithLatencyInfo(
const MouseEventWithLatencyInfo& mouse_event) {
TRACE_EVENT2("input", "RenderWidgetHostImpl::ForwardMouseEvent",
"x", mouse_event.event.x, "y", mouse_event.event.y);
+
+ for (size_t i = 0; i < mouse_event_callbacks_.size(); ++i) {
+ if (mouse_event_callbacks_[i].Run(mouse_event.event))
+ return;
+ }
+
input_router_->SendMouseEvent(mouse_event);
}
@@ -1117,15 +1174,35 @@ ui::LatencyInfo RenderWidgetHostImpl::CreateRWHLatencyInfoIfNotExist(
}
-void RenderWidgetHostImpl::AddKeyboardListener(KeyboardListener* listener) {
- keyboard_listeners_.AddObserver(listener);
+void RenderWidgetHostImpl::AddKeyPressEventCallback(
+ const KeyPressEventCallback& callback) {
+ key_press_event_callbacks_.push_back(callback);
+}
+
+void RenderWidgetHostImpl::RemoveKeyPressEventCallback(
+ const KeyPressEventCallback& callback) {
+ for (size_t i = 0; i < key_press_event_callbacks_.size(); ++i) {
+ if (key_press_event_callbacks_[i].Equals(callback)) {
+ key_press_event_callbacks_.erase(
+ key_press_event_callbacks_.begin() + i);
+ return;
+ }
+ }
+}
+
+void RenderWidgetHostImpl::AddMouseEventCallback(
+ const MouseEventCallback& callback) {
+ mouse_event_callbacks_.push_back(callback);
}
-void RenderWidgetHostImpl::RemoveKeyboardListener(
- KeyboardListener* listener) {
- // Ensure that the element is actually an observer.
- DCHECK(keyboard_listeners_.HasObserver(listener));
- keyboard_listeners_.RemoveObserver(listener);
+void RenderWidgetHostImpl::RemoveMouseEventCallback(
+ const MouseEventCallback& callback) {
+ for (size_t i = 0; i < mouse_event_callbacks_.size(); ++i) {
+ if (mouse_event_callbacks_[i].Equals(callback)) {
+ mouse_event_callbacks_.erase(mouse_event_callbacks_.begin() + i);
+ return;
+ }
+ }
}
void RenderWidgetHostImpl::GetWebScreenInfo(WebKit::WebScreenInfo* result) {
@@ -1134,6 +1211,7 @@ void RenderWidgetHostImpl::GetWebScreenInfo(WebKit::WebScreenInfo* result) {
static_cast<RenderWidgetHostViewPort*>(GetView())->GetScreenInfo(result);
else
RenderWidgetHostViewPort::GetDefaultScreenInfo(result);
+ screen_info_out_of_date_ = false;
}
const NativeWebKeyboardEvent*
@@ -1150,6 +1228,7 @@ void RenderWidgetHostImpl::NotifyScreenInfoChanged() {
}
void RenderWidgetHostImpl::InvalidateScreenInfo() {
+ screen_info_out_of_date_ = true;
screen_info_.reset();
}
@@ -1200,7 +1279,8 @@ 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, routing_id_));
+ input_router_.reset(
+ new ImmediateInputRouter(process_, this, this, routing_id_));
if (overscroll_controller_)
overscroll_controller_->Reset();
@@ -1262,7 +1342,7 @@ void RenderWidgetHostImpl::ImeSetComposition(
void RenderWidgetHostImpl::ImeConfirmComposition(
const string16& text,
- const ui::Range& replacement_range,
+ const gfx::Range& replacement_range,
bool keep_selection) {
Send(new ViewMsg_ImeConfirmComposition(
GetRoutingID(), text, replacement_range, keep_selection));
@@ -1482,7 +1562,9 @@ bool RenderWidgetHostImpl::OnSwapCompositorFrame(
ack.gl_frame_data = frame->gl_frame_data.Pass();
ack.gl_frame_data->sync_point = 0;
} else if (frame->delegated_frame_data) {
- ack.resources.swap(frame->delegated_frame_data->resource_list);
+ cc::TransferableResource::ReturnResources(
+ frame->delegated_frame_data->resource_list,
+ &ack.resources);
} else if (frame->software_frame_data) {
ack.last_software_frame_id = frame->software_frame_data->id;
}
@@ -1665,7 +1747,14 @@ void RenderWidgetHostImpl::OnBeginSmoothScroll(
const ViewHostMsg_BeginSmoothScroll_Params& params) {
if (!view_)
return;
- smooth_scroll_gesture_controller_.BeginSmoothScroll(view_, params);
+ synthetic_gesture_controller_.BeginSmoothScroll(view_, params);
+}
+
+void RenderWidgetHostImpl::OnBeginPinch(
+ const ViewHostMsg_BeginPinch_Params& params) {
+ if (!view_)
+ return;
+ synthetic_gesture_controller_.BeginPinch(view_, params);
}
void RenderWidgetHostImpl::OnFocus() {
@@ -1689,15 +1778,15 @@ void RenderWidgetHostImpl::OnSetCursor(const WebCursor& cursor) {
void RenderWidgetHostImpl::OnTextInputTypeChanged(
ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) {
+ ui::TextInputMode input_mode,
+ bool can_compose_inline) {
if (view_)
- view_->TextInputTypeChanged(type, can_compose_inline, input_mode);
+ view_->TextInputTypeChanged(type, input_mode, can_compose_inline);
}
#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
void RenderWidgetHostImpl::OnImeCompositionRangeChanged(
- const ui::Range& range,
+ const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) {
if (view_)
view_->ImeCompositionRangeChanged(range, character_bounds);
@@ -1879,10 +1968,8 @@ bool RenderWidgetHostImpl::KeyPressListenersHandleEvent(
if (event.skip_in_browser || event.type != WebKeyboardEvent::RawKeyDown)
return false;
- ObserverList<KeyboardListener>::Iterator it(keyboard_listeners_);
- KeyboardListener* listener;
- while ((listener = it.GetNext()) != NULL) {
- if (listener->HandleKeyPressEvent(event))
+ for (size_t i = 0; i < key_press_event_callbacks_.size(); i++) {
+ if (key_press_event_callbacks_[i].Run(event))
return true;
}
@@ -2067,6 +2154,12 @@ bool RenderWidgetHostImpl::OnSendGestureEventImmediately(
return !IgnoreInputEvents();
}
+void RenderWidgetHostImpl::SetNeedsFlush() {
+}
+
+void RenderWidgetHostImpl::DidFlush() {
+}
+
void RenderWidgetHostImpl::OnKeyboardEventAck(
const NativeWebKeyboardEvent& event,
InputEventAckState ack_result) {
@@ -2118,13 +2211,13 @@ void RenderWidgetHostImpl::OnTouchEventAck(
view_->ProcessAckedTouchEvent(event, ack_result);
}
-void RenderWidgetHostImpl::OnUnexpectedEventAck(bool bad_message) {
- if (bad_message) {
+void RenderWidgetHostImpl::OnUnexpectedEventAck(UnexpectedEventAckType type) {
+ if (type == BAD_ACK_MESSAGE) {
RecordAction(UserMetricsAction("BadMessageTerminate_RWH2"));
process_->ReceivedBadMessage();
+ } else if (type == UNEXPECTED_EVENT_TYPE) {
+ suppress_next_char_events_ = false;
}
-
- suppress_next_char_events_ = false;
}
const gfx::Vector2d& RenderWidgetHostImpl::GetLastScrollOffset() const {
@@ -2144,10 +2237,6 @@ bool RenderWidgetHostImpl::ShouldForwardGestureEvent(
return input_router_->ShouldForwardGestureEvent(gesture_event);
}
-bool RenderWidgetHostImpl::HasQueuedGestureEvents() const {
- return input_router_->HasQueuedGestureEvents();
-}
-
void RenderWidgetHostImpl::StartUserGesture() {
OnUserGesture();
}
@@ -2331,6 +2420,19 @@ void RenderWidgetHostImpl::SendSwapCompositorFrameAck(
route_id, output_surface_id, ack));
}
+// static
+void RenderWidgetHostImpl::SendReclaimCompositorResources(
+ int32 route_id,
+ uint32 output_surface_id,
+ int renderer_host_id,
+ const cc::CompositorFrameAck& ack) {
+ RenderProcessHost* host = RenderProcessHost::FromID(renderer_host_id);
+ if (!host)
+ return;
+ host->Send(
+ new ViewMsg_ReclaimCompositorResources(route_id, output_surface_id, ack));
+}
+
void RenderWidgetHostImpl::AcknowledgeSwapBuffersToRenderer() {
if (!is_threaded_compositing_enabled_)
Send(new ViewMsg_SwapBuffers_ACK(routing_id_));
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 362c6d7f793..613177c9a81 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_impl.h
@@ -23,8 +23,9 @@
#include "base/time/time.h"
#include "base/timer/timer.h"
#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/smooth_scroll_gesture_controller.h"
+#include "content/browser/renderer_host/synthetic_gesture_controller.h"
#include "content/common/browser_rendering_stats.h"
#include "content/common/view_message_enums.h"
#include "content/port/browser/event_with_latency_info.h"
@@ -34,7 +35,7 @@
#include "ipc/ipc_listener.h"
#include "ui/base/ime/text_input_mode.h"
#include "ui/base/ime/text_input_type.h"
-#include "ui/base/latency_info.h"
+#include "ui/events/latency_info.h"
#include "ui/gfx/native_widget_types.h"
class WebCursor;
@@ -53,9 +54,12 @@ class CompositorFrame;
class CompositorFrameAck;
}
+namespace gfx {
+class Range;
+}
+
namespace ui {
class KeyEvent;
-class Range;
}
namespace WebKit {
@@ -78,13 +82,14 @@ class MockRenderWidgetHost;
class OverscrollController;
class RenderWidgetHostDelegate;
class RenderWidgetHostViewPort;
-class SmoothScrollGestureController;
+class SyntheticGestureController;
struct EditCommand;
// This implements the RenderWidgetHost interface that is exposed to
// embedders of content, and adds things only visible to content.
class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
public InputRouterClient,
+ public InputAckHandler,
public IPC::Listener {
public:
// routing_id can be MSG_ROUTING_NONE, in which case the next available
@@ -93,7 +98,8 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
// |delegate| goes away.
RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
RenderProcessHost* process,
- int routing_id);
+ int routing_id,
+ bool hidden);
virtual ~RenderWidgetHostImpl();
// Similar to RenderWidgetHost::FromID, but returning the Impl object.
@@ -102,14 +108,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
// Returns all RenderWidgetHosts including swapped out ones for
// internal use. The public interface
// RendgerWidgetHost::GetRenderWidgetHosts only returns active ones.
- // Keep in mind that there may be dependencies between these
- // widgets. If a caller indirectly causes one of the widgets to be
- // deleted while iterating over the list, the deleted widget will
- // stay in the list and possibly causes a use-after-free. Take care
- // to avoid deleting widgets as you iterate (e.g., see
- // http://crbug.com/259859). TODO(nasko): Improve this interface to
- // better prevent UaFs.
- static std::vector<RenderWidgetHost*> GetAllRenderWidgetHosts();
+ static scoped_ptr<RenderWidgetHostIterator> GetAllRenderWidgetHosts();
// Use RenderWidgetHostImpl::From(rwh) to downcast a
// RenderWidgetHost to a RenderWidgetHostImpl. Internally, this
@@ -172,8 +171,14 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
virtual void SetIgnoreInputEvents(bool ignore_input_events) OVERRIDE;
virtual void Stop() OVERRIDE;
virtual void WasResized() OVERRIDE;
- virtual void AddKeyboardListener(KeyboardListener* listener) OVERRIDE;
- virtual void RemoveKeyboardListener(KeyboardListener* listener) OVERRIDE;
+ virtual void AddKeyPressEventCallback(
+ const KeyPressEventCallback& callback) OVERRIDE;
+ virtual void RemoveKeyPressEventCallback(
+ const KeyPressEventCallback& callback) OVERRIDE;
+ virtual void AddMouseEventCallback(
+ const MouseEventCallback& callback) OVERRIDE;
+ virtual void RemoveMouseEventCallback(
+ const MouseEventCallback& callback) OVERRIDE;
virtual void GetWebScreenInfo(WebKit::WebScreenInfo* result) OVERRIDE;
virtual void GetSnapshotFromRenderer(
const gfx::Rect& src_subrect,
@@ -199,7 +204,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
// Called when a renderer object already been created for this host, and we
// just need to be attached to it. Used for window.open, <select> dropdown
// menus, and other times when the renderer initiates creating an object.
- void Init();
+ virtual void Init();
// Tells the renderer to die and then calls Destroy().
virtual void Shutdown();
@@ -267,9 +272,9 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
void DonePaintingToBackingStore();
// GPU accelerated version of GetBackingStore function. This will
- // trigger a re-composite to the view. If a resize is pending, it will
- // block briefly waiting for an ack from the renderer.
- void ScheduleComposite();
+ // trigger a re-composite to the view. It may fail if a resize is pending, or
+ // if a composite has already been requested and not acked yet.
+ bool ScheduleComposite();
// Starts a hang monitor timeout. If there's already a hang monitor timeout
// the new one will only fire if it has a shorter delay than the time
@@ -335,7 +340,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
// * when it receives a "commit" signal of GtkIMContext (on Linux);
// * when insertText of NSTextInput is called (on Mac).
void ImeConfirmComposition(const string16& text,
- const ui::Range& replacement_range,
+ const gfx::Range& replacement_range,
bool keep_selection);
// Cancels an ongoing composition.
@@ -365,7 +370,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
bool ShouldForwardTouchEvent() const;
bool ShouldForwardGestureEvent(
const GestureEventWithLatencyInfo& gesture_event) const;
- bool HasQueuedGestureEvents() const;
bool has_touch_handler() const { return has_touch_handler_; }
@@ -463,6 +467,12 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
int renderer_host_id,
const cc::CompositorFrameAck& ack);
+ // Called by the view to return resources to the compositor.
+ static void SendReclaimCompositorResources(int32 route_id,
+ uint32 output_surface_id,
+ int renderer_host_id,
+ const cc::CompositorFrameAck& ack);
+
// Called by the view in response to AcceleratedSurfaceBuffersSwapped for
// platforms that support deferred GPU process descheduling. This does
// nothing if the compositor thread is enabled.
@@ -503,7 +513,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
return overscroll_controller_.get();
}
- base::TimeDelta GetSyntheticScrollMessageInterval() const;
+ base::TimeDelta GetSyntheticGestureMessageInterval() const;
// Sets whether the overscroll controller should be enabled for this page.
void SetOverscrollControllerEnabled(bool enabled);
@@ -648,15 +658,17 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
void OnUpdateIsDelayed();
void OnBeginSmoothScroll(
const ViewHostMsg_BeginSmoothScroll_Params& params);
+ void OnBeginPinch(
+ const ViewHostMsg_BeginPinch_Params& params);
virtual void OnFocus();
virtual void OnBlur();
void OnSetCursor(const WebCursor& cursor);
void OnTextInputTypeChanged(ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode);
+ ui::TextInputMode input_mode,
+ bool can_compose_inline);
#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
void OnImeCompositionRangeChanged(
- const ui::Range& range,
+ const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds);
#endif
void OnImeCancelComposition();
@@ -729,6 +741,10 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
const TouchEventWithLatencyInfo& touch_event) OVERRIDE;
virtual bool OnSendGestureEventImmediately(
const GestureEventWithLatencyInfo& gesture_event) OVERRIDE;
+ virtual void SetNeedsFlush() OVERRIDE;
+ virtual void DidFlush() OVERRIDE;
+
+ // InputAckHandler
virtual void OnKeyboardEventAck(const NativeWebKeyboardEvent& event,
InputEventAckState ack_result) OVERRIDE;
virtual void OnWheelEventAck(const WebKit::WebMouseWheelEvent& event,
@@ -737,7 +753,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
InputEventAckState ack_result) OVERRIDE;
virtual void OnGestureEventAck(const WebKit::WebGestureEvent& event,
InputEventAckState ack_result) OVERRIDE;
- virtual void OnUnexpectedEventAck(bool bad_message) OVERRIDE;
+ virtual void OnUnexpectedEventAck(UnexpectedEventAckType type) OVERRIDE;
void SimulateTouchGestureWithMouse(const WebKit::WebMouseEvent& mouse_event);
@@ -745,7 +761,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
// which may get in recursive loops).
void DelayedAutoResized();
-
// Our delegate, which wants to know mainly about keyboard events.
// It will remain non-NULL until DetachDelegate() is called.
RenderWidgetHostDelegate* delegate_;
@@ -821,7 +836,10 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
AccessibilityMode accessibility_mode_;
// Keyboard event listeners.
- ObserverList<KeyboardListener> keyboard_listeners_;
+ std::vector<KeyPressEventCallback> key_press_event_callbacks_;
+
+ // Mouse event callbacks.
+ std::vector<MouseEventCallback> mouse_event_callbacks_;
// If true, then we should repaint when restoring even if we have a
// backingstore. This flag is set to true if we receive a paint message
@@ -899,7 +917,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
base::WeakPtrFactory<RenderWidgetHostImpl> weak_factory_;
- SmoothScrollGestureController smooth_scroll_gesture_controller_;
+ SyntheticGestureController synthetic_gesture_controller_;
// Receives and handles all input events.
scoped_ptr<InputRouter> input_router_;
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 960ce5eb92a..21c368ab488 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "base/basictypes.h"
+#include "base/bind.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/shared_memory.h"
#include "base/timer/timer.h"
@@ -28,7 +29,7 @@
#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/base/keycodes/keyboard_codes.h"
+#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/screen.h"
@@ -40,7 +41,7 @@
#if defined(OS_WIN) || defined(USE_AURA)
#include "content/browser/renderer_host/ui_events_helper.h"
-#include "ui/base/events/event.h"
+#include "ui/events/event.h"
#endif
using base::TimeDelta;
@@ -104,30 +105,6 @@ class TestOverscrollDelegate : public OverscrollControllerDelegate {
DISALLOW_COPY_AND_ASSIGN(TestOverscrollDelegate);
};
-// MockKeyboardListener --------------------------------------------------------
-class MockKeyboardListener : public KeyboardListener {
- public:
- MockKeyboardListener()
- : handle_key_press_event_(false) {
- }
- virtual ~MockKeyboardListener() {}
-
- // KeyboardListener:
- virtual bool HandleKeyPressEvent(
- const NativeWebKeyboardEvent& event) OVERRIDE {
- return handle_key_press_event_;
- }
-
- void set_handle_key_press_event(bool handle) {
- handle_key_press_event_ = handle;
- }
-
- private:
- bool handle_key_press_event_;
-
- DISALLOW_COPY_AND_ASSIGN(MockKeyboardListener);
-};
-
// MockInputRouter -------------------------------------------------------------
class MockInputRouter : public InputRouter {
@@ -145,12 +122,11 @@ class MockInputRouter : public InputRouter {
virtual ~MockInputRouter() {}
// InputRouter
- virtual bool SendInput(IPC::Message* message) OVERRIDE {
+ virtual void Flush() OVERRIDE {
+ flush_called_ = true;
+ }
+ virtual bool SendInput(scoped_ptr<IPC::Message> message) OVERRIDE {
send_event_called_ = true;
-
- // SendInput takes ownership of message
- delete message;
-
return true;
}
virtual void SendMouseEvent(
@@ -195,7 +171,6 @@ class MockInputRouter : public InputRouter {
const GestureEventWithLatencyInfo& gesture_event) const OVERRIDE {
return true;
}
- virtual bool HasQueuedGestureEvents() const OVERRIDE { return true; }
// IPC::Listener
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
@@ -203,6 +178,7 @@ class MockInputRouter : public InputRouter {
return false;
}
+ bool flush_called_;
bool send_event_called_;
bool sent_mouse_event_;
bool sent_wheel_event_;
@@ -225,7 +201,7 @@ class MockRenderWidgetHost : public RenderWidgetHostImpl {
RenderWidgetHostDelegate* delegate,
RenderProcessHost* process,
int routing_id)
- : RenderWidgetHostImpl(delegate, process, routing_id),
+ : RenderWidgetHostImpl(delegate, process, routing_id, false),
unresponsive_timer_fired_(false) {
immediate_input_router_ =
static_cast<ImmediateInputRouter*>(input_router_.get());
@@ -628,11 +604,21 @@ class MockPaintingObserver : public NotificationObserver {
class RenderWidgetHostTest : public testing::Test {
public:
- RenderWidgetHostTest() : process_(NULL) {
+ RenderWidgetHostTest()
+ : process_(NULL),
+ handle_key_press_event_(false),
+ handle_mouse_event_(false) {
}
virtual ~RenderWidgetHostTest() {
}
+ bool KeyPressEventCallback(const NativeWebKeyboardEvent& /* event */) {
+ return handle_key_press_event_;
+ }
+ bool MouseEventCallback(const WebKit::WebMouseEvent& /* event */) {
+ return handle_mouse_event_;
+ }
+
protected:
// testing::Test
virtual void SetUp() {
@@ -835,6 +821,8 @@ class RenderWidgetHostTest : public testing::Test {
scoped_ptr<MockRenderWidgetHost> host_;
scoped_ptr<TestView> view_;
scoped_ptr<gfx::Screen> screen_;
+ bool handle_key_press_event_;
+ bool handle_mouse_event_;
private:
WebTouchEvent touch_event_;
@@ -857,13 +845,12 @@ class RenderWidgetHostWithSourceTest
// -----------------------------------------------------------------------------
TEST_F(RenderWidgetHostTest, Resize) {
- // The initial bounds is the empty rect, but the screen info hasn't been sent
- // yet, so setting it to the same thing should send the resize message.
+ // The initial bounds is the empty rect, and the screen info hasn't been sent
+ // yet, so setting it to the same thing shouldn't send the resize message.
view_->set_bounds(gfx::Rect());
host_->WasResized();
EXPECT_FALSE(host_->resize_ack_pending_);
- EXPECT_EQ(gfx::Size(), host_->last_requested_size_);
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
+ EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
// Setting the bounds to a "real" rect should send out the notification.
// but should not expect ack for empty physical backing size.
@@ -1397,6 +1384,7 @@ TEST_F(RenderWidgetHostTest, WheelScrollEventOverscrolls) {
SimulateMouseMove(5, 10, 0);
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_mode());
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_delegate()->current_mode());
+ EXPECT_EQ(1U, process_->sink().message_count());
}
// Tests that if some scroll events are consumed towards the start, then
@@ -1618,10 +1606,10 @@ TEST_F(RenderWidgetHostTest, ScrollEventsOverscrollWithZeroFling) {
// Send a fling start, but with a small velocity, so that the overscroll is
// aborted. The fling should proceed to the renderer, through the gesture
// event filter.
- SimulateGestureFlingStartEvent(0.f, 0.f, WebGestureEvent::Touchpad);
+ SimulateGestureFlingStartEvent(10.f, 0.f, WebGestureEvent::Touchpad);
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_mode());
- EXPECT_EQ(0U, host_->GestureEventLastQueueEventSize());
- EXPECT_EQ(0U, process_->sink().message_count());
+ EXPECT_EQ(1U, host_->GestureEventLastQueueEventSize());
+ EXPECT_EQ(1U, process_->sink().message_count());
}
// Tests that a fling in the opposite direction of the overscroll cancels the
@@ -1646,11 +1634,13 @@ TEST_F(RenderWidgetHostTest, ReverseFlingCancelsOverscroll) {
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(OVERSCROLL_EAST, host_->overscroll_mode());
EXPECT_EQ(OVERSCROLL_EAST, host_->overscroll_delegate()->current_mode());
+ process_->sink().ClearMessages();
SimulateGestureEvent(WebInputEvent::GestureScrollEnd,
WebGestureEvent::Touchscreen);
EXPECT_EQ(OVERSCROLL_EAST, host_->overscroll_delegate()->completed_mode());
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_delegate()->current_mode());
+ EXPECT_EQ(1U, process_->sink().message_count());
SendInputEventACK(WebInputEvent::GestureScrollEnd,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
}
@@ -1670,9 +1660,12 @@ TEST_F(RenderWidgetHostTest, ReverseFlingCancelsOverscroll) {
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(OVERSCROLL_WEST, host_->overscroll_mode());
EXPECT_EQ(OVERSCROLL_WEST, host_->overscroll_delegate()->current_mode());
+ process_->sink().ClearMessages();
+
SimulateGestureFlingStartEvent(100, 0, WebGestureEvent::Touchscreen);
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_delegate()->completed_mode());
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_delegate()->current_mode());
+ EXPECT_EQ(1U, process_->sink().message_count());
}
}
@@ -1750,11 +1743,14 @@ TEST_F(RenderWidgetHostTest, GestureScrollConsumedHorizontal) {
INPUT_EVENT_ACK_STATE_CONSUMED);
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_mode());
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_delegate()->current_mode());
+ process_->sink().ClearMessages();
// Send another gesture event and ACK as not being processed. This should
// not initiate overscroll because the beginning of the scroll event did
- // scroll some content on the page.
+ // scroll some content on the page. Since there was no overscroll, the event
+ // should reach the renderer.
SimulateGestureScrollUpdateEvent(55, 0, 0);
+ EXPECT_EQ(1U, process_->sink().message_count());
SendInputEventACK(WebInputEvent::GestureScrollUpdate,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_mode());
@@ -2301,12 +2297,15 @@ TEST_F(RenderWidgetHostTest, OverscrollMouseMoveCompletion) {
// Overscroll gesture is in progress. Send a mouse-move now. This should
// complete the gesture (because the amount overscrolled is above the
- // threshold), and consume the event.
+ // threshold).
SimulateMouseMove(5, 10, 0);
EXPECT_EQ(OVERSCROLL_EAST, host_->overscroll_delegate()->completed_mode());
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_mode());
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_delegate()->current_mode());
- EXPECT_EQ(0U, process_->sink().message_count());
+ EXPECT_EQ(1U, process_->sink().message_count());
+ process_->sink().ClearMessages();
+ SendInputEventACK(WebInputEvent::MouseMove,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
SimulateGestureEvent(WebInputEvent::GestureScrollEnd,
WebGestureEvent::Touchscreen);
@@ -2499,32 +2498,30 @@ TEST_F(RenderWidgetHostTest, IgnoreInputEvent) {
TEST_F(RenderWidgetHostTest, KeyboardListenerIgnoresEvent) {
host_->SetupForInputRouterTest();
-
- scoped_ptr<MockKeyboardListener> keyboard_listener_(new MockKeyboardListener);
- host_->AddKeyboardListener(keyboard_listener_.get());
-
- keyboard_listener_->set_handle_key_press_event(false);
+ host_->AddKeyPressEventCallback(
+ base::Bind(&RenderWidgetHostTest::KeyPressEventCallback,
+ base::Unretained(this)));
+ handle_key_press_event_ = false;
SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
EXPECT_TRUE(host_->mock_input_router()->sent_keyboard_event_);
-
- host_->RemoveKeyboardListener(keyboard_listener_.get());
}
TEST_F(RenderWidgetHostTest, KeyboardListenerSuppressFollowingEvents) {
host_->SetupForInputRouterTest();
- scoped_ptr<MockKeyboardListener> keyboard_listener_(new MockKeyboardListener);
- host_->AddKeyboardListener(keyboard_listener_.get());
+ host_->AddKeyPressEventCallback(
+ base::Bind(&RenderWidgetHostTest::KeyPressEventCallback,
+ base::Unretained(this)));
- // KeyboardListener handles the first event
- keyboard_listener_->set_handle_key_press_event(true);
+ // The callback handles the first event
+ handle_key_press_event_ = true;
SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
EXPECT_FALSE(host_->mock_input_router()->sent_keyboard_event_);
// Following Char events should be suppressed
- keyboard_listener_->set_handle_key_press_event(false);
+ handle_key_press_event_ = false;
SimulateKeyboardEvent(WebInputEvent::Char);
EXPECT_FALSE(host_->mock_input_router()->sent_keyboard_event_);
SimulateKeyboardEvent(WebInputEvent::Char);
@@ -2537,8 +2534,24 @@ TEST_F(RenderWidgetHostTest, KeyboardListenerSuppressFollowingEvents) {
host_->mock_input_router()->sent_keyboard_event_ = false;
SimulateKeyboardEvent(WebInputEvent::Char);
EXPECT_TRUE(host_->mock_input_router()->sent_keyboard_event_);
+}
+
+TEST_F(RenderWidgetHostTest, MouseEventCallbackCanHandleEvent) {
+ host_->SetupForInputRouterTest();
+
+ host_->AddMouseEventCallback(
+ base::Bind(&RenderWidgetHostTest::MouseEventCallback,
+ base::Unretained(this)));
+
+ handle_mouse_event_ = true;
+ SimulateMouseEvent(WebInputEvent::MouseDown);
+
+ EXPECT_FALSE(host_->mock_input_router()->sent_mouse_event_);
+
+ handle_mouse_event_ = false;
+ SimulateMouseEvent(WebInputEvent::MouseDown);
- host_->RemoveKeyboardListener(keyboard_listener_.get());
+ EXPECT_TRUE(host_->mock_input_router()->sent_mouse_event_);
}
TEST_F(RenderWidgetHostTest, InputRouterReceivesHandleInputEvent_ACK) {
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 8e885407e5c..3b94566748f 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
@@ -6,8 +6,9 @@
#include <android/bitmap.h>
+#include "base/basictypes.h"
#include "base/bind.h"
-#include "base/bind_helpers.h"
+#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
@@ -20,6 +21,7 @@
#include "cc/output/compositor_frame_ack.h"
#include "cc/output/copy_output_request.h"
#include "cc/output/copy_output_result.h"
+#include "cc/resources/single_release_callback.h"
#include "cc/trees/layer_tree_host.h"
#include "content/browser/accessibility/browser_accessibility_manager_android.h"
#include "content/browser/android/content_view_core_impl.h"
@@ -28,10 +30,10 @@
#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/render_widget_host_impl.h"
#include "content/browser/renderer_host/surface_texture_transport_client_android.h"
-#include "content/browser/renderer_host/touch_smooth_scroll_gesture_android.h"
#include "content/common/gpu/client/gl_helper.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/common/input_messages.h"
@@ -51,6 +53,7 @@ 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) {
@@ -88,12 +91,12 @@ void SendImeEventAck(RenderWidgetHostImpl* host) {
void CopyFromCompositingSurfaceFinished(
const base::Callback<void(bool, const SkBitmap&)>& callback,
- const cc::TextureMailbox::ReleaseCallback& release_callback,
+ scoped_ptr<cc::SingleReleaseCallback> release_callback,
scoped_ptr<SkBitmap> bitmap,
scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock,
bool result) {
bitmap_pixels_lock.reset();
- release_callback.Run(0, false);
+ release_callback->Run(0, false);
callback.Run(result, *bitmap);
}
@@ -196,7 +199,7 @@ RenderWidgetHostViewAndroid::GetRenderWidgetHost() const {
}
void RenderWidgetHostViewAndroid::WasShown() {
- if (!host_->is_hidden())
+ if (!host_ || !host_->is_hidden())
return;
host_->WasShown();
@@ -205,7 +208,7 @@ void RenderWidgetHostViewAndroid::WasShown() {
void RenderWidgetHostViewAndroid::WasHidden() {
RunAckCallbacks();
- if (host_->is_hidden())
+ if (!host_ || host_->is_hidden())
return;
// Inform the renderer that we are being hidden so it can reduce its resource
@@ -353,6 +356,8 @@ void RenderWidgetHostViewAndroid::Show() {
are_layers_attached_ = true;
AttachLayers();
+
+ WasShown();
}
void RenderWidgetHostViewAndroid::Hide() {
@@ -361,6 +366,8 @@ void RenderWidgetHostViewAndroid::Hide() {
are_layers_attached_ = false;
RemoveLayers();
+
+ WasHidden();
}
bool RenderWidgetHostViewAndroid::IsShowing() {
@@ -406,8 +413,8 @@ void RenderWidgetHostViewAndroid::SetIsLoading(bool is_loading) {
void RenderWidgetHostViewAndroid::TextInputTypeChanged(
ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) {
+ ui::TextInputMode input_mode,
+ bool can_compose_inline) {
// Unused on Android, which uses OnTextInputChanged instead.
}
@@ -420,9 +427,9 @@ void RenderWidgetHostViewAndroid::OnTextInputStateChanged(
// If an acknowledgement is required for this event, regardless of how we exit
// from this method, we must acknowledge that we processed the input state
// change.
- base::ScopedClosureRunner ack_caller(base::Bind(&SendImeEventAck, host_));
- if (!params.require_ack)
- ack_caller.Release();
+ base::ScopedClosureRunner ack_caller;
+ if (params.require_ack)
+ ack_caller.Reset(base::Bind(&SendImeEventAck, host_));
if (!IsShowing())
return;
@@ -510,7 +517,7 @@ void RenderWidgetHostViewAndroid::SetTooltipText(
void RenderWidgetHostViewAndroid::SelectionChanged(const string16& text,
size_t offset,
- const ui::Range& range) {
+ const gfx::Range& range) {
RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
if (text.empty() || range.is_empty() || !content_view_core_)
@@ -606,14 +613,28 @@ void RenderWidgetHostViewAndroid::ShowDisambiguationPopup(
content_view_core_->ShowDisambiguationPopup(target_rect, zoomed_bitmap);
}
-SmoothScrollGesture* RenderWidgetHostViewAndroid::CreateSmoothScrollGesture(
+SyntheticGesture* RenderWidgetHostViewAndroid::CreateSmoothScrollGesture(
bool scroll_down, int pixels_to_scroll, int mouse_event_x,
int mouse_event_y) {
- return new TouchSmoothScrollGestureAndroid(
- pixels_to_scroll,
+ 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_->CreateSmoothScroller(
- scroll_down, mouse_event_x, mouse_event_y));
+ 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));
}
void RenderWidgetHostViewAndroid::OnAcceleratedCompositingStateChange() {
@@ -828,7 +849,7 @@ void RenderWidgetHostViewAndroid::CreateOverscrollEffectIfNecessary() {
if (!overscroll_effect_enabled_ || overscroll_effect_)
return;
- overscroll_effect_ = OverscrollGlow::Create(true);
+ overscroll_effect_ = OverscrollGlow::Create(true, content_size_in_layer_);
// Prevent future creation attempts on failure.
if (!overscroll_effect_)
@@ -950,8 +971,8 @@ InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent(
return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
}
-void RenderWidgetHostViewAndroid::OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>& params) {
+void RenderWidgetHostViewAndroid::OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>& params) {
if (!host_ ||
host_->accessibility_mode() != AccessibilityModeComplete ||
!content_view_core_) {
@@ -965,7 +986,7 @@ void RenderWidgetHostViewAndroid::OnAccessibilityNotifications(
BrowserAccessibilityManagerAndroid::GetEmptyDocument(),
this));
}
- GetBrowserAccessibilityManager()->OnAccessibilityNotifications(params);
+ GetBrowserAccessibilityManager()->OnAccessibilityEvents(params);
}
void RenderWidgetHostViewAndroid::SetAccessibilityFocus(int acc_obj_id) {
@@ -1183,6 +1204,7 @@ WebKit::WebGraphicsContext3D* RenderWidgetHostViewAndroid::Context3d() {
bool RenderWidgetHostViewAndroid::PrepareTextureMailbox(
cc::TextureMailbox* mailbox,
+ scoped_ptr<cc::SingleReleaseCallback>* release_callback,
bool use_shared_memory) {
return false;
}
@@ -1223,23 +1245,25 @@ void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult(
new SkAutoLockPixels(*bitmap));
uint8* pixels = static_cast<uint8*>(bitmap->getPixels());
- scoped_ptr<cc::TextureMailbox> texture_mailbox = result->TakeTexture();
- DCHECK(texture_mailbox->IsTexture());
- if (!texture_mailbox->IsTexture())
+ 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;
- scoped_callback_runner.Release();
+ ignore_result(scoped_callback_runner.Release());
gl_helper->CropScaleReadbackAndCleanMailbox(
- texture_mailbox->name(),
- texture_mailbox->sync_point(),
+ texture_mailbox.name(),
+ texture_mailbox.sync_point(),
result->size(),
gfx::Rect(result->size()),
dst_size_in_pixel,
pixels,
base::Bind(&CopyFromCompositingSurfaceFinished,
callback,
- texture_mailbox->callback(),
+ base::Passed(&release_callback),
base::Passed(&bitmap),
base::Passed(&bitmap_pixels_lock)));
}
@@ -1264,7 +1288,7 @@ void RenderWidgetHostViewAndroid::PrepareBitmapCopyOutputResult(
DCHECK_EQ(source->width(), dst_size_in_pixel.width());
DCHECK_EQ(source->height(), dst_size_in_pixel.height());
- scoped_callback_runner.Release();
+ ignore_result(scoped_callback_runner.Release());
callback.Run(true, *source);
}
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 d8ea83da7ce..6f248076e97 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
@@ -36,6 +36,7 @@ namespace cc {
class CopyOutputResult;
class DelegatedRendererLayer;
class Layer;
+class SingleReleaseCallback;
class TextureLayer;
}
@@ -98,8 +99,8 @@ class RenderWidgetHostViewAndroid
virtual void UpdateCursor(const WebCursor& cursor) OVERRIDE;
virtual void SetIsLoading(bool is_loading) OVERRIDE;
virtual void TextInputTypeChanged(ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) OVERRIDE;
+ ui::TextInputMode input_mode,
+ bool can_compose_inline) OVERRIDE;
virtual void ImeCancelComposition() OVERRIDE;
virtual void DidUpdateBackingStore(
const gfx::Rect& scroll_rect,
@@ -112,7 +113,7 @@ class RenderWidgetHostViewAndroid
virtual void SetTooltipText(const string16& tooltip_text) OVERRIDE;
virtual void SelectionChanged(const string16& text,
size_t offset,
- const ui::Range& range) OVERRIDE;
+ const gfx::Range& range) OVERRIDE;
virtual void SelectionBoundsChanged(
const ViewHostMsg_SelectionBounds_Params& params) OVERRIDE;
virtual void ScrollOffsetChanged() OVERRIDE;
@@ -152,8 +153,8 @@ class RenderWidgetHostViewAndroid
const WebKit::WebInputEvent& input_event) OVERRIDE;
virtual void GestureEventAck(int gesture_event_type,
InputEventAckState ack_result) OVERRIDE;
- virtual void OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>&
+ virtual void OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>&
params) OVERRIDE;
virtual bool LockMouse() OVERRIDE;
virtual void UnlockMouse() OVERRIDE;
@@ -165,9 +166,12 @@ class RenderWidgetHostViewAndroid
gfx::Vector2dF current_fling_velocity) OVERRIDE;
virtual void ShowDisambiguationPopup(const gfx::Rect& target_rect,
const SkBitmap& zoomed_bitmap) OVERRIDE;
- virtual SmoothScrollGesture* CreateSmoothScrollGesture(
+ 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;
// Implementation of BrowserAccessibilityDelegate:
virtual void SetAccessibilityFocus(int acc_obj_id) OVERRIDE;
@@ -184,8 +188,10 @@ class RenderWidgetHostViewAndroid
// cc::TextureLayerClient implementation.
virtual unsigned PrepareTexture() OVERRIDE;
virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE;
- virtual bool PrepareTextureMailbox(cc::TextureMailbox* mailbox,
- bool use_shared_memory) OVERRIDE;
+ virtual bool PrepareTextureMailbox(
+ cc::TextureMailbox* mailbox,
+ scoped_ptr<cc::SingleReleaseCallback>* release_callback,
+ bool use_shared_memory) OVERRIDE;
// cc::DelegatedRendererLayerClient implementation.
virtual void DidCommitFrameData() OVERRIDE;
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 33ee9524e73..2eb34b98d38 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,8 +4,9 @@
#include "content/browser/renderer_host/render_widget_host_view_aura.h"
+#include "base/basictypes.h"
#include "base/bind.h"
-#include "base/bind_helpers.h"
+#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/logging.h"
@@ -16,8 +17,11 @@
#include "cc/output/copy_output_request.h"
#include "cc/output/copy_output_result.h"
#include "cc/resources/texture_mailbox.h"
+#include "cc/trees/layer_tree_settings.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
+#include "content/browser/aura/compositor_resize_lock.h"
+#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/overscroll_controller.h"
@@ -57,13 +61,13 @@
#include "ui/aura/window_observer.h"
#include "ui/aura/window_tracker.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
-#include "ui/base/events/event.h"
-#include "ui/base/events/event_utils.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/gfx/canvas.h"
#include "ui/gfx/display.h"
#include "ui/gfx/rect_conversions.h"
@@ -77,6 +81,7 @@
#include "content/browser/accessibility/browser_accessibility_win.h"
#include "ui/base/win/hidden_window.h"
#include "ui/gfx/gdi_util.h"
+#include "ui/gfx/win/dpi.h"
#endif
using gfx::RectToSkIRect;
@@ -100,10 +105,10 @@ class MemoryHolder : public base::RefCounted<MemoryHolder> {
frame_size_(frame_size),
callback_(callback) {}
- cc::TextureMailbox GetMailbox() {
- return cc::TextureMailbox(
- shared_memory_.get(),
- frame_size_,
+ 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)));
}
@@ -118,6 +123,11 @@ class MemoryHolder : public base::RefCounted<MemoryHolder> {
namespace {
+void MailboxReleaseCallback(scoped_ptr<base::SharedMemory> shared_memory,
+ unsigned sync_point, bool lost_resource) {
+ // NOTE: shared_memory will get released when we go out of scope.
+}
+
// In mouse lock mode, we need to prevent the (invisible) cursor from hitting
// the border of the view, in order to get valid movement information. However,
// forcing the cursor back to the center of the view after each mouse move
@@ -567,73 +577,6 @@ class RenderWidgetHostViewAura::TransientWindowObserver
#endif
-class RenderWidgetHostViewAura::ResizeLock {
- public:
- ResizeLock(aura::RootWindow* root_window,
- const gfx::Size new_size,
- bool defer_compositor_lock)
- : root_window_(root_window),
- new_size_(new_size),
- compositor_lock_(defer_compositor_lock ?
- NULL :
- root_window_->compositor()->GetCompositorLock()),
- weak_ptr_factory_(this),
- defer_compositor_lock_(defer_compositor_lock) {
- TRACE_EVENT_ASYNC_BEGIN2("ui", "ResizeLock", this,
- "width", new_size_.width(),
- "height", new_size_.height());
- root_window_->HoldPointerMoves();
-
- BrowserThread::PostDelayedTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&RenderWidgetHostViewAura::ResizeLock::CancelLock,
- weak_ptr_factory_.GetWeakPtr()),
- base::TimeDelta::FromMilliseconds(kResizeLockTimeoutMs));
- }
-
- ~ResizeLock() {
- CancelLock();
- TRACE_EVENT_ASYNC_END2("ui", "ResizeLock", this,
- "width", new_size_.width(),
- "height", new_size_.height());
- }
-
- void UnlockCompositor() {
- defer_compositor_lock_ = false;
- compositor_lock_ = NULL;
- }
-
- void CancelLock() {
- if (!root_window_)
- return;
- UnlockCompositor();
- root_window_->ReleasePointerMoves();
- root_window_ = NULL;
- }
-
- const gfx::Size& expected_size() const {
- return new_size_;
- }
-
- bool GrabDeferredLock() {
- if (root_window_ && defer_compositor_lock_) {
- compositor_lock_ = root_window_->compositor()->GetCompositorLock();
- defer_compositor_lock_ = false;
- return true;
- }
- return false;
- }
-
- private:
- aura::RootWindow* root_window_;
- gfx::Size new_size_;
- scoped_refptr<ui::CompositorLock> compositor_lock_;
- base::WeakPtrFactory<ResizeLock> weak_ptr_factory_;
- bool defer_compositor_lock_;
-
- DISALLOW_COPY_AND_ASSIGN(ResizeLock);
-};
-
////////////////////////////////////////////////////////////////////////////////
// RenderWidgetHostViewAura, public:
@@ -646,8 +589,11 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host)
popup_child_host_view_(NULL),
is_loading_(false),
text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
+ text_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT),
can_compose_inline_(true),
has_composition_text_(false),
+ last_output_surface_id_(0),
+ skipped_frames_(false),
last_swapped_surface_scale_factor_(1.f),
paint_canvas_(NULL),
synthetic_move_sent_(false),
@@ -746,18 +692,26 @@ RenderWidgetHost* RenderWidgetHostViewAura::GetRenderWidgetHost() const {
}
void RenderWidgetHostViewAura::WasShown() {
+ DCHECK(host_);
if (!host_->is_hidden())
return;
host_->WasShown();
+ if (framebuffer_holder_)
+ FrameMemoryManager::GetInstance()->SetFrameVisibility(this, true);
- aura::client::CursorClient* cursor_client =
- aura::client::GetCursorClient(window_->GetRootWindow());
- if (cursor_client)
- NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
+ aura::RootWindow* root = window_->GetRootWindow();
+ if (root) {
+ aura::client::CursorClient* cursor_client =
+ aura::client::GetCursorClient(root);
+ if (cursor_client)
+ NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
+ }
if (!current_surface_.get() && host_->is_accelerated_compositing_active() &&
!released_front_lock_.get()) {
- released_front_lock_ = GetCompositor()->GetCompositorLock();
+ ui::Compositor* compositor = GetCompositor();
+ if (compositor)
+ released_front_lock_ = compositor->GetCompositorLock();
}
#if defined(OS_WIN)
@@ -768,9 +722,11 @@ void RenderWidgetHostViewAura::WasShown() {
}
void RenderWidgetHostViewAura::WasHidden() {
- if (host_->is_hidden())
+ if (!host_ || host_->is_hidden())
return;
host_->WasHidden();
+ if (framebuffer_holder_)
+ FrameMemoryManager::GetInstance()->SetFrameVisibility(this, false);
released_front_lock_ = NULL;
@@ -803,39 +759,69 @@ void RenderWidgetHostViewAura::SetBounds(const gfx::Rect& rect) {
}
void RenderWidgetHostViewAura::MaybeCreateResizeLock() {
- gfx::Size desired_size = window_->bounds().size();
- if (!host_->should_auto_resize() &&
- !resize_lock_.get() &&
- desired_size != current_frame_size_ &&
- host_->is_accelerated_compositing_active()) {
- aura::RootWindow* root_window = window_->GetRootWindow();
- ui::Compositor* compositor = root_window ?
- root_window->compositor() : NULL;
- if (root_window && compositor) {
- // Listen to changes in the compositor lock state.
- if (!compositor->HasObserver(this))
- compositor->AddObserver(this);
-
-// On Windows while resizing, the the resize locks makes us mis-paint a white
-// vertical strip (including the non-client area) if the content composition is
-// lagging the UI composition. So here we disable the throttling so that the UI
-// bits can draw ahead of the content thereby reducing the amount of whiteout.
-// Because this causes the content to be drawn at wrong sizes while resizing
-// we compensate by blocking the UI thread in Compositor::Draw() by issuing a
-// FinishAllRendering() if we are resizing.
-#if !defined (OS_WIN)
- bool defer_compositor_lock =
- can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
- can_lock_compositor_ == NO_PENDING_COMMIT;
-
- if (can_lock_compositor_ == YES)
- can_lock_compositor_ = YES_DID_LOCK;
-
- resize_lock_.reset(new ResizeLock(root_window, desired_size,
- defer_compositor_lock));
+ if (!ShouldCreateResizeLock())
+ return;
+ DCHECK(window_->GetRootWindow());
+ DCHECK(window_->GetRootWindow()->compositor());
+
+ // Listen to changes in the compositor lock state.
+ ui::Compositor* compositor = window_->GetRootWindow()->compositor();
+ if (!compositor->HasObserver(this))
+ compositor->AddObserver(this);
+
+ bool defer_compositor_lock =
+ can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
+ can_lock_compositor_ == NO_PENDING_COMMIT;
+
+ if (can_lock_compositor_ == YES)
+ can_lock_compositor_ = YES_DID_LOCK;
+
+ resize_lock_ = CreateResizeLock(defer_compositor_lock);
+}
+
+bool RenderWidgetHostViewAura::ShouldCreateResizeLock() {
+ // On Windows while resizing, the the resize locks makes us mis-paint a white
+ // vertical strip (including the non-client area) if the content composition
+ // is lagging the UI composition. So here we disable the throttling so that
+ // the UI bits can draw ahead of the content thereby reducing the amount of
+ // whiteout. Because this causes the content to be drawn at wrong sizes while
+ // resizing we compensate by blocking the UI thread in Compositor::Draw() by
+ // issuing a FinishAllRendering() if we are resizing.
+#if defined (OS_WIN)
+ return false;
#endif
- }
- }
+
+ if (resize_lock_)
+ return false;
+
+ if (host_->should_auto_resize())
+ return false;
+ if (!host_->is_accelerated_compositing_active())
+ return false;
+
+ gfx::Size desired_size = window_->bounds().size();
+ if (desired_size == current_frame_size_)
+ return false;
+
+ aura::RootWindow* root_window = window_->GetRootWindow();
+ if (!root_window)
+ return false;
+
+ ui::Compositor* compositor = root_window->compositor();
+ if (!compositor)
+ return false;
+
+ return true;
+}
+
+scoped_ptr<ResizeLock> RenderWidgetHostViewAura::CreateResizeLock(
+ bool defer_compositor_lock) {
+ gfx::Size desired_size = window_->bounds().size();
+ return scoped_ptr<ResizeLock>(new CompositorResizeLock(
+ window_->GetRootWindow(),
+ desired_size,
+ defer_compositor_lock,
+ base::TimeDelta::FromMilliseconds(kResizeLockTimeoutMs)));
}
gfx::NativeView RenderWidgetHostViewAura::GetNativeView() const {
@@ -983,10 +969,12 @@ bool RenderWidgetHostViewAura::IsSurfaceAvailableForCopy() const {
void RenderWidgetHostViewAura::Show() {
window_->Show();
+ WasShown();
}
void RenderWidgetHostViewAura::Hide() {
window_->Hide();
+ WasHidden();
}
bool RenderWidgetHostViewAura::IsShowing() {
@@ -1010,18 +998,6 @@ void RenderWidgetHostViewAura::SetBackground(const SkBitmap& background) {
window_->layer()->SetFillsBoundsOpaquely(background.isOpaque());
}
-#if defined(OS_WIN)
-gfx::NativeViewAccessible
-RenderWidgetHostViewAura::AccessibleObjectFromChildId(long child_id) {
- BrowserAccessibilityManager* manager = GetBrowserAccessibilityManager();
- if (!manager)
- return NULL;
-
- return manager->ToBrowserAccessibilityManagerWin()->GetFromUniqueIdWin(
- child_id);
-}
-#endif // defined(OS_WIN)
-
void RenderWidgetHostViewAura::UpdateCursor(const WebCursor& cursor) {
current_cursor_ = cursor;
const gfx::Display display = gfx::Screen::GetScreenFor(window_)->
@@ -1039,11 +1015,13 @@ void RenderWidgetHostViewAura::SetIsLoading(bool is_loading) {
void RenderWidgetHostViewAura::TextInputTypeChanged(
ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) {
+ ui::TextInputMode input_mode,
+ bool can_compose_inline) {
if (text_input_type_ != type ||
+ text_input_mode_ != input_mode ||
can_compose_inline_ != can_compose_inline) {
text_input_type_ = type;
+ text_input_mode_ = input_mode;
can_compose_inline_ = can_compose_inline;
if (GetInputMethod())
GetInputMethod()->OnTextInputTypeChanged(this);
@@ -1059,7 +1037,7 @@ void RenderWidgetHostViewAura::ImeCancelComposition() {
}
void RenderWidgetHostViewAura::ImeCompositionRangeChanged(
- const ui::Range& range,
+ const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) {
composition_character_bounds_ = character_bounds;
}
@@ -1144,7 +1122,7 @@ void RenderWidgetHostViewAura::SetTooltipText(const string16& tooltip_text) {
void RenderWidgetHostViewAura::SelectionChanged(const string16& text,
size_t offset,
- const ui::Range& range) {
+ const gfx::Range& range) {
RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
#if defined(USE_X11) && !defined(OS_CHROMEOS)
@@ -1308,9 +1286,14 @@ 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_) {
- cc::TextureMailbox mailbox = framebuffer_holder_->GetMailbox();
+ cc::TextureMailbox mailbox;
+ scoped_ptr<cc::SingleReleaseCallback> callback;
+ framebuffer_holder_->GetMailbox(&mailbox, &callback);
window_->layer()->SetTextureMailbox(mailbox,
+ callback.Pass(),
last_swapped_surface_scale_factor_);
current_frame_size_ = ConvertSizeToDIP(last_swapped_surface_scale_factor_,
mailbox.shared_memory_size());
@@ -1319,6 +1302,8 @@ void RenderWidgetHostViewAura::UpdateExternalTexture() {
window_->layer()->SetExternalTexture(NULL);
resize_lock_.reset();
host_->WasResized();
+ framebuffer_holder_ = NULL;
+ FrameMemoryManager::GetInstance()->RemoveFrame(this);
}
}
@@ -1440,20 +1425,58 @@ 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;
+
if (!frame_data->render_pass_list.empty()) {
- frame_size_in_dip = gfx::ToFlooredSize(gfx::ScaleSize(
- frame_data->render_pass_list.back()->output_rect.size(),
- 1.f/frame_device_scale_factor));
+ 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);
+
+ 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);
}
+
+ framebuffer_holder_ = NULL;
+ FrameMemoryManager::GetInstance()->RemoveFrame(this);
+
if (ShouldSkipFrame(frame_size_in_dip)) {
cc::CompositorFrameAck ack;
- ack.resources.swap(frame_data->resource_list);
+ cc::TransferableResource::ReturnResources(frame_data->resource_list,
+ &ack.resources);
RenderWidgetHostImpl::SendSwapCompositorFrameAck(
host_->GetRoutingID(), output_surface_id,
host_->GetProcess()->GetID(), ack);
+ skipped_frames_ = true;
return;
}
+
+ if (skipped_frames_) {
+ skipped_frames_ = false;
+ damage_rect = gfx::Rect(frame_size);
+ damage_rect_in_dip = gfx::Rect(frame_size_in_dip);
+
+ // Give the same damage rect to the compositor.
+ cc::RenderPass* root_pass = frame_data->render_pass_list.back();
+ root_pass->damage_rect = damage_rect;
+ }
+
+ if (output_surface_id != last_output_surface_id_) {
+ // Resource ids are scoped by the output surface.
+ // If the originating output surface doesn't match the last one, it
+ // 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);
+ last_output_surface_id_ = output_surface_id;
+ }
window_->layer()->SetDelegatedFrame(frame_data.Pass(), frame_size_in_dip);
released_front_lock_ = NULL;
current_frame_size_ = frame_size_in_dip;
@@ -1461,6 +1484,7 @@ void RenderWidgetHostViewAura::SwapDelegatedFrame(
if (paint_observer_)
paint_observer_->OnUpdateCompositorContent();
+ window_->SchedulePaintInRect(damage_rect_in_dip);
ui::Compositor* compositor = GetCompositor();
if (!compositor) {
@@ -1493,7 +1517,8 @@ void RenderWidgetHostViewAura::SwapSoftwareFrame(
gfx::Size frame_size_in_dip =
ConvertSizeToDIP(frame_device_scale_factor, frame_size);
if (ShouldSkipFrame(frame_size_in_dip)) {
- SendSoftwareFrameAck(output_surface_id, frame_data->id);
+ ReleaseSoftwareFrame(output_surface_id, frame_data->id);
+ SendSoftwareFrameAck(output_surface_id);
return;
}
@@ -1522,41 +1547,83 @@ void RenderWidgetHostViewAura::SwapSoftwareFrame(
scoped_refptr<MemoryHolder> holder(new MemoryHolder(
shared_memory.Pass(),
frame_size,
- base::Bind(&RenderWidgetHostViewAura::SendSoftwareFrameAck,
+ base::Bind(&RenderWidgetHostViewAura::ReleaseSoftwareFrame,
AsWeakPtr(),
output_surface_id,
frame_data->id)));
framebuffer_holder_.swap(holder);
- cc::TextureMailbox mailbox = framebuffer_holder_->GetMailbox();
+ cc::TextureMailbox mailbox;
+ scoped_ptr<cc::SingleReleaseCallback> callback;
+ framebuffer_holder_->GetMailbox(&mailbox, &callback);
DCHECK(mailbox.IsSharedMemory());
current_frame_size_ = frame_size_in_dip;
released_front_lock_ = NULL;
CheckResizeLock();
- window_->layer()->SetTextureMailbox(mailbox, frame_device_scale_factor);
+ window_->layer()->SetTextureMailbox(mailbox,
+ callback.Pass(),
+ frame_device_scale_factor);
window_->SchedulePaintInRect(
ConvertRectToDIP(frame_device_scale_factor, damage_rect));
ui::Compositor* compositor = GetCompositor();
- if (compositor)
+ if (compositor) {
compositor->SetLatencyInfo(latency_info);
+ AddOnCommitCallbackAndDisableLocks(
+ base::Bind(&RenderWidgetHostViewAura::SendSoftwareFrameAck,
+ AsWeakPtr(),
+ output_surface_id));
+ }
if (paint_observer_)
paint_observer_->OnUpdateCompositorContent();
DidReceiveFrameFromRenderer();
+ FrameMemoryManager::GetInstance()->AddFrame(this, !host_->is_hidden());
}
-void RenderWidgetHostViewAura::SendSoftwareFrameAck(
- uint32 output_surface_id, unsigned software_frame_id) {
+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();
+ }
+ }
+
cc::CompositorFrameAck ack;
ack.last_software_frame_id = software_frame_id;
RenderWidgetHostImpl::SendSwapCompositorFrameAck(
host_->GetRoutingID(), output_surface_id,
host_->GetProcess()->GetID(), ack);
+ SendReclaimSoftwareFrames();
+}
+
+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();
+ }
+}
+
+void RenderWidgetHostViewAura::ReleaseSoftwareFrame(
+ uint32 output_surface_id,
+ unsigned software_frame_id) {
+ SendReclaimSoftwareFrames();
+ released_software_frames_.push_back(
+ ReleasedFrameInfo(output_surface_id, software_frame_id));
}
void RenderWidgetHostViewAura::OnSwapCompositorFrame(
uint32 output_surface_id,
scoped_ptr<cc::CompositorFrame> frame) {
+ TRACE_EVENT0("content", "RenderWidgetHostViewAura::OnSwapCompositorFrame");
if (frame->delegated_frame_data) {
SwapDelegatedFrame(output_surface_id,
frame->delegated_frame_data.Pass(),
@@ -1620,6 +1687,8 @@ 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);
if (!SwapBuffersPrepare(surface_rect,
surface_scale_factor,
@@ -1724,7 +1793,7 @@ void RenderWidgetHostViewAura::AcceleratedSurfaceRelease() {
}
bool RenderWidgetHostViewAura::HasAcceleratedSurface(
- const gfx::Size& desired_size) {
+ const gfx::Size& desired_size) {
// Aura doesn't use GetBackingStore for accelerated pages, so it doesn't
// matter what is returned here as GetBackingStore is the only caller of this
// method. TODO(jbates) implement this if other Aura code needs it.
@@ -1756,12 +1825,12 @@ void RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResult(
static void CopyFromCompositingSurfaceFinished(
const base::Callback<void(bool, const SkBitmap&)>& callback,
- const cc::TextureMailbox::ReleaseCallback& release_callback,
+ scoped_ptr<cc::SingleReleaseCallback> release_callback,
scoped_ptr<SkBitmap> bitmap,
scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock,
bool result) {
bitmap_pixels_lock.reset();
- release_callback.Run(0, false);
+ release_callback->Run(0, false);
callback.Run(result, *bitmap);
}
@@ -1793,23 +1862,25 @@ void RenderWidgetHostViewAura::PrepareTextureCopyOutputResult(
new SkAutoLockPixels(*bitmap));
uint8* pixels = static_cast<uint8*>(bitmap->getPixels());
- scoped_ptr<cc::TextureMailbox> texture_mailbox = result->TakeTexture();
- DCHECK(texture_mailbox->IsTexture());
- if (!texture_mailbox->IsTexture())
+ 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;
- scoped_callback_runner.Release();
+ ignore_result(scoped_callback_runner.Release());
gl_helper->CropScaleReadbackAndCleanMailbox(
- texture_mailbox->name(),
- texture_mailbox->sync_point(),
+ texture_mailbox.name(),
+ texture_mailbox.sync_point(),
result->size(),
gfx::Rect(result->size()),
dst_size_in_pixel,
pixels,
base::Bind(&CopyFromCompositingSurfaceFinished,
callback,
- texture_mailbox->callback(),
+ base::Passed(&release_callback),
base::Passed(&bitmap),
base::Passed(&bitmap_pixels_lock)));
}
@@ -1831,7 +1902,7 @@ void RenderWidgetHostViewAura::PrepareBitmapCopyOutputResult(
if (!source)
return;
- scoped_callback_runner.Release();
+ ignore_result(scoped_callback_runner.Release());
SkBitmap bitmap = skia::ImageOperations::Resize(
*source,
@@ -1843,9 +1914,9 @@ void RenderWidgetHostViewAura::PrepareBitmapCopyOutputResult(
static void CopyFromCompositingSurfaceFinishedForVideo(
const base::Callback<void(bool)>& callback,
- const cc::TextureMailbox::ReleaseCallback& release_callback,
+ scoped_ptr<cc::SingleReleaseCallback> release_callback,
bool result) {
- release_callback.Run(0, false);
+ release_callback->Run(0, false);
callback.Run(result);
}
@@ -1908,7 +1979,7 @@ void RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResultForVideo(
region_in_frame,
video_frame.get());
}
- scoped_callback_runner.Release();
+ ignore_result(scoped_callback_runner.Release());
callback.Run(true);
return;
}
@@ -1918,9 +1989,11 @@ void RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResultForVideo(
if (!gl_helper)
return;
- scoped_ptr<cc::TextureMailbox> texture_mailbox = result->TakeTexture();
- DCHECK(texture_mailbox->IsTexture());
- if (!texture_mailbox->IsTexture())
+ 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());
@@ -1958,14 +2031,14 @@ void RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResultForVideo(
yuv_readback_pipeline = rwhva->yuv_readback_pipeline_.get();
}
- scoped_callback_runner.Release();
+ ignore_result(scoped_callback_runner.Release());
base::Callback<void(bool result)> finished_callback = base::Bind(
&CopyFromCompositingSurfaceFinishedForVideo,
callback,
- texture_mailbox->callback());
+ base::Passed(&release_callback));
yuv_readback_pipeline->ReadbackYUV(
- texture_mailbox->name(),
- texture_mailbox->sync_point(),
+ texture_mailbox.name(),
+ texture_mailbox.sync_point(),
video_frame.get(),
finished_callback);
}
@@ -1975,7 +2048,32 @@ void RenderWidgetHostViewAura::GetScreenInfo(WebScreenInfo* results) {
}
gfx::Rect RenderWidgetHostViewAura::GetBoundsInRootWindow() {
+#if defined(OS_WIN)
+ // aura::Window::GetBoundsInScreen doesn't take non-client area into
+ // account.
+ RECT window_rect = {0};
+
+ aura::Window* top_level = window_->GetToplevelWindow();
+ aura::RootWindow* root_window = top_level->GetRootWindow();
+ if (!root_window)
+ return top_level->GetBoundsInScreen();
+ HWND hwnd = root_window->GetAcceleratedWidget();
+ ::GetWindowRect(hwnd, &window_rect);
+ gfx::Rect rect(window_rect);
+
+ // Maximized windows are outdented from the work area by the frame thickness
+ // even though this "frame" is not painted. This confuses code (and people)
+ // that think of a maximized window as corresponding exactly to the work area.
+ // Correct for this by subtracting the frame thickness back off.
+ if (::IsZoomed(hwnd)) {
+ rect.Inset(GetSystemMetrics(SM_CXSIZEFRAME),
+ GetSystemMetrics(SM_CYSIZEFRAME));
+ }
+
+ return gfx::win::ScreenToDIPRect(rect);
+#else
return window_->GetToplevelWindow()->GetBoundsInScreen();
+#endif
}
void RenderWidgetHostViewAura::GestureEventAck(int gesture_event_type,
@@ -2004,7 +2102,7 @@ void RenderWidgetHostViewAura::ProcessAckedTouchEvent(
}
}
-SmoothScrollGesture* RenderWidgetHostViewAura::CreateSmoothScrollGesture(
+SyntheticGesture* RenderWidgetHostViewAura::CreateSmoothScrollGesture(
bool scroll_down,
int pixels_to_scroll,
int mouse_event_x,
@@ -2026,12 +2124,12 @@ void RenderWidgetHostViewAura::SetScrollOffsetPinning(
// Not needed. Mac-only.
}
-void RenderWidgetHostViewAura::OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>& params) {
+void RenderWidgetHostViewAura::OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>& params) {
BrowserAccessibilityManager* manager =
GetOrCreateBrowserAccessibilityManager();
if (manager)
- manager->OnAccessibilityNotifications(params);
+ manager->OnAccessibilityEvents(params);
}
gfx::GLSurfaceHandle RenderWidgetHostViewAura::GetCompositingSurface() {
@@ -2122,7 +2220,7 @@ void RenderWidgetHostViewAura::SetCompositionText(
void RenderWidgetHostViewAura::ConfirmCompositionText() {
if (host_ && has_composition_text_)
- host_->ImeConfirmComposition(string16(), ui::Range::InvalidRange(), false);
+ host_->ImeConfirmComposition(string16(), gfx::Range::InvalidRange(), false);
has_composition_text_ = false;
}
@@ -2135,7 +2233,7 @@ void RenderWidgetHostViewAura::ClearCompositionText() {
void RenderWidgetHostViewAura::InsertText(const string16& text) {
DCHECK(text_input_type_ != ui::TEXT_INPUT_TYPE_NONE);
if (host_)
- host_->ImeConfirmComposition(text, ui::Range::InvalidRange(), false);
+ host_->ImeConfirmComposition(text, gfx::Range::InvalidRange(), false);
has_composition_text_ = false;
}
@@ -2166,7 +2264,7 @@ ui::TextInputType RenderWidgetHostViewAura::GetTextInputType() const {
}
ui::TextInputMode RenderWidgetHostViewAura::GetTextInputMode() const {
- return ui::TEXT_INPUT_MODE_DEFAULT;
+ return text_input_mode_;
}
bool RenderWidgetHostViewAura::CanComposeInline() const {
@@ -2178,18 +2276,18 @@ gfx::Rect RenderWidgetHostViewAura::ConvertRectToScreen(const gfx::Rect& rect) {
gfx::Point end = gfx::Point(rect.right(), rect.bottom());
aura::RootWindow* root_window = window_->GetRootWindow();
- if (root_window) {
- aura::client::ScreenPositionClient* screen_position_client =
- aura::client::GetScreenPositionClient(root_window);
- screen_position_client->ConvertPointToScreen(window_, &origin);
- screen_position_client->ConvertPointToScreen(window_, &end);
- return gfx::Rect(origin.x(),
- origin.y(),
- end.x() - origin.x(),
- end.y() - origin.y());
- }
-
- return rect;
+ if (!root_window)
+ return rect;
+ aura::client::ScreenPositionClient* screen_position_client =
+ aura::client::GetScreenPositionClient(root_window);
+ if (!screen_position_client)
+ return rect;
+ screen_position_client->ConvertPointToScreen(window_, &origin);
+ screen_position_client->ConvertPointToScreen(window_, &end);
+ return gfx::Rect(origin.x(),
+ origin.y(),
+ end.x() - origin.x(),
+ end.y() - origin.y());
}
gfx::Rect RenderWidgetHostViewAura::ConvertRectFromScreen(
@@ -2231,40 +2329,40 @@ bool RenderWidgetHostViewAura::HasCompositionText() {
return has_composition_text_;
}
-bool RenderWidgetHostViewAura::GetTextRange(ui::Range* range) {
+bool RenderWidgetHostViewAura::GetTextRange(gfx::Range* range) {
range->set_start(selection_text_offset_);
range->set_end(selection_text_offset_ + selection_text_.length());
return true;
}
-bool RenderWidgetHostViewAura::GetCompositionTextRange(ui::Range* range) {
+bool RenderWidgetHostViewAura::GetCompositionTextRange(gfx::Range* range) {
// TODO(suzhe): implement this method when fixing http://crbug.com/55130.
NOTIMPLEMENTED();
return false;
}
-bool RenderWidgetHostViewAura::GetSelectionRange(ui::Range* range) {
+bool RenderWidgetHostViewAura::GetSelectionRange(gfx::Range* range) {
range->set_start(selection_range_.start());
range->set_end(selection_range_.end());
return true;
}
-bool RenderWidgetHostViewAura::SetSelectionRange(const ui::Range& range) {
+bool RenderWidgetHostViewAura::SetSelectionRange(const gfx::Range& range) {
// TODO(suzhe): implement this method when fixing http://crbug.com/55130.
NOTIMPLEMENTED();
return false;
}
-bool RenderWidgetHostViewAura::DeleteRange(const ui::Range& range) {
+bool RenderWidgetHostViewAura::DeleteRange(const gfx::Range& range) {
// TODO(suzhe): implement this method when fixing http://crbug.com/55130.
NOTIMPLEMENTED();
return false;
}
bool RenderWidgetHostViewAura::GetTextFromRange(
- const ui::Range& range,
+ const gfx::Range& range,
string16* text) {
- ui::Range selection_text_range(selection_text_offset_,
+ gfx::Range selection_text_range(selection_text_offset_,
selection_text_offset_ + selection_text_.length());
if (!selection_text_range.Contains(range)) {
@@ -2446,6 +2544,13 @@ void RenderWidgetHostViewAura::OnWindowDestroying() {
LPARAM lparam = reinterpret_cast<LPARAM>(this);
EnumChildWindows(parent, WindowDestroyingCallback, lparam);
#endif
+
+ // Make sure that the input method no longer references to this object before
+ // this object is removed from the root window (i.e. this object loses access
+ // to the input method).
+ ui::InputMethod* input_method = GetInputMethod();
+ if (input_method)
+ input_method->DetachTextInputClient(this);
}
void RenderWidgetHostViewAura::OnWindowDestroyed() {
@@ -2463,28 +2568,53 @@ bool RenderWidgetHostViewAura::HasHitTestMask() const {
void RenderWidgetHostViewAura::GetHitTestMask(gfx::Path* mask) const {
}
-scoped_refptr<ui::Texture> RenderWidgetHostViewAura::CopyTexture() {
- if (!host_->is_accelerated_compositing_active())
- return scoped_refptr<ui::Texture>();
-
- ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- GLHelper* gl_helper = factory->GetGLHelper();
- if (!gl_helper)
- return scoped_refptr<ui::Texture>();
-
- if (!current_surface_.get())
- return scoped_refptr<ui::Texture>();
-
- WebKit::WebGLId texture_id =
- gl_helper->CopyTexture(current_surface_->PrepareTexture(),
- current_surface_->size());
- if (!texture_id)
- return scoped_refptr<ui::Texture>();
-
- return scoped_refptr<ui::Texture>(
- factory->CreateOwnedTexture(
+void RenderWidgetHostViewAura::DidRecreateLayer(ui::Layer *old_layer,
+ ui::Layer *new_layer) {
+ float mailbox_scale_factor;
+ cc::TextureMailbox old_mailbox =
+ old_layer->GetTextureMailbox(&mailbox_scale_factor);
+ scoped_refptr<ui::Texture> old_texture = old_layer->external_texture();
+ // The new_layer is the one that will be used by our Window, so that's the one
+ // that should keep our texture. old_layer will be returned to the
+ // RecreateLayer caller, and should have a copy.
+ if (old_texture.get()) {
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ GLHelper* gl_helper = factory->GetGLHelper();
+ scoped_refptr<ui::Texture> new_texture;
+ if (host_->is_accelerated_compositing_active() &&
+ gl_helper && current_surface_.get()) {
+ WebKit::WebGLId texture_id =
+ gl_helper->CopyTexture(current_surface_->PrepareTexture(),
+ current_surface_->size());
+ if (texture_id) {
+ new_texture = factory->CreateOwnedTexture(
current_surface_->size(),
- current_surface_->device_scale_factor(), texture_id));
+ current_surface_->device_scale_factor(), texture_id);
+ }
+ }
+ old_layer->SetExternalTexture(new_texture);
+ new_layer->SetExternalTexture(old_texture);
+ } else if (old_mailbox.IsSharedMemory()) {
+ base::SharedMemory* old_buffer = old_mailbox.shared_memory();
+ const size_t size = old_mailbox.shared_memory_size_in_bytes();
+
+ scoped_ptr<base::SharedMemory> new_buffer(new base::SharedMemory);
+ new_buffer->CreateAndMapAnonymous(size);
+
+ if (old_buffer->memory() && new_buffer->memory()) {
+ memcpy(new_buffer->memory(), old_buffer->memory(), size);
+ base::SharedMemory* new_buffer_raw_ptr = new_buffer.get();
+ scoped_ptr<cc::SingleReleaseCallback> callback =
+ cc::SingleReleaseCallback::Create(base::Bind(MailboxReleaseCallback,
+ Passed(&new_buffer)));
+ cc::TextureMailbox new_mailbox(new_buffer_raw_ptr,
+ old_mailbox.shared_memory_size());
+ new_layer->SetTextureMailbox(new_mailbox,
+ callback.Pass(),
+ mailbox_scale_factor);
+ }
+ }
+ // TODO(piman): handle delegated frames.
}
////////////////////////////////////////////////////////////////////////////////
@@ -2859,6 +2989,18 @@ void RenderWidgetHostViewAura::OnRootWindowHostMoved(
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, ui::CompositorObserver implementation:
@@ -2908,8 +3050,17 @@ void RenderWidgetHostViewAura::OnUpdateVSyncParameters(
ui::Compositor* compositor,
base::TimeTicks timebase,
base::TimeDelta interval) {
- if (IsShowing() && !last_draw_ended_.is_null())
- host_->UpdateVSyncParameters(last_draw_ended_, interval);
+ if (IsShowing()) {
+ if (IsDeadlineSchedulingEnabled()) {
+ // The deadline scheduler has logic to stagger the draws of the
+ // Renderer and Browser built-in, so send it an accurate timebase.
+ host_->UpdateVSyncParameters(timebase, interval);
+ } else if (!last_draw_ended_.is_null()) {
+ // For the non-deadline scheduler, we send the Renderer an offset
+ // vsync timebase to avoid its draws racing the Browser's draws.
+ host_->UpdateVSyncParameters(last_draw_ended_, interval);
+ }
+ }
}
////////////////////////////////////////////////////////////////////////////////
@@ -3021,6 +3172,7 @@ 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);
}
void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() {
@@ -3034,8 +3186,10 @@ void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() {
gfx::Point local_point = screen_point;
local_point.Offset(-screen_rect.x(), -screen_rect.y());
- if (root_window->GetEventHandlerForPoint(local_point) != window_)
+ if (!root_window->HasFocus() ||
+ root_window->GetEventHandlerForPoint(local_point) != window_) {
return;
+ }
gfx::NativeCursor cursor = current_cursor_.GetNativeCursor();
// Do not show loading cursor when the cursor is currently hidden.
@@ -3064,7 +3218,7 @@ void RenderWidgetHostViewAura::FinishImeCompositionSession() {
if (!has_composition_text_)
return;
if (host_)
- host_->ImeConfirmComposition(string16(), ui::Range::InvalidRange(), false);
+ host_->ImeConfirmComposition(string16(), gfx::Range::InvalidRange(), false);
ImeCancelComposition();
}
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 c4a16271634..f5939df0fc7 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
@@ -18,6 +18,7 @@
#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/renderer_host/render_widget_host_view_base.h"
#include "content/common/content_export.h"
#include "content/common/gpu/client/gl_helper.h"
@@ -59,9 +60,10 @@ namespace content {
class MemoryHolder;
class RenderWidgetHostImpl;
class RenderWidgetHostView;
+class ResizeLock;
// RenderWidgetHostView class hierarchy described in render_widget_host_view.h.
-class RenderWidgetHostViewAura
+class CONTENT_EXPORT RenderWidgetHostViewAura
: public RenderWidgetHostViewBase,
public ui::CompositorObserver,
public ui::TextInputClient,
@@ -74,6 +76,7 @@ class RenderWidgetHostViewAura
public aura::client::CursorClientObserver,
public ImageTransportFactoryObserver,
public BrowserAccessibilityDelegate,
+ public FrameContainer,
public base::SupportsWeakPtr<RenderWidgetHostViewAura> {
public:
// Used to notify whenever the paint-content of the view changes.
@@ -155,10 +158,6 @@ class RenderWidgetHostViewAura
virtual bool IsShowing() OVERRIDE;
virtual gfx::Rect GetViewBounds() const OVERRIDE;
virtual void SetBackground(const SkBitmap& background) OVERRIDE;
-#if defined(OS_WIN)
- virtual gfx::NativeViewAccessible AccessibleObjectFromChildId(long child_id)
- OVERRIDE;
-#endif
// Overridden from RenderWidgetHostViewPort:
virtual void InitAsPopup(RenderWidgetHostView* parent_host_view,
@@ -175,11 +174,11 @@ class RenderWidgetHostViewAura
virtual void UpdateCursor(const WebCursor& cursor) OVERRIDE;
virtual void SetIsLoading(bool is_loading) OVERRIDE;
virtual void TextInputTypeChanged(ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) OVERRIDE;
+ ui::TextInputMode input_mode,
+ bool can_compose_inline) OVERRIDE;
virtual void ImeCancelComposition() OVERRIDE;
virtual void ImeCompositionRangeChanged(
- const ui::Range& range,
+ const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) OVERRIDE;
virtual void DidUpdateBackingStore(
const gfx::Rect& scroll_rect,
@@ -192,7 +191,7 @@ class RenderWidgetHostViewAura
virtual void SetTooltipText(const string16& tooltip_text) OVERRIDE;
virtual void SelectionChanged(const string16& text,
size_t offset,
- const ui::Range& range) OVERRIDE;
+ const gfx::Range& range) OVERRIDE;
virtual void SelectionBoundsChanged(
const ViewHostMsg_SelectionBounds_Params& params) OVERRIDE;
virtual void ScrollOffsetChanged() OVERRIDE;
@@ -227,7 +226,7 @@ class RenderWidgetHostViewAura
virtual void ProcessAckedTouchEvent(
const TouchEventWithLatencyInfo& touch,
InputEventAckState ack_result) OVERRIDE;
- virtual SmoothScrollGesture* CreateSmoothScrollGesture(
+ virtual SyntheticGesture* CreateSmoothScrollGesture(
bool scroll_down,
int pixels_to_scroll,
int mouse_event_x,
@@ -237,8 +236,8 @@ class RenderWidgetHostViewAura
virtual void SetScrollOffsetPinning(
bool is_pinned_to_left, bool is_pinned_to_right) OVERRIDE;
virtual gfx::GLSurfaceHandle GetCompositingSurface() OVERRIDE;
- virtual void OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>&
+ virtual void OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>&
params) OVERRIDE;
virtual bool LockMouse() OVERRIDE;
virtual void UnlockMouse() OVERRIDE;
@@ -265,12 +264,12 @@ class RenderWidgetHostViewAura
virtual bool GetCompositionCharacterBounds(uint32 index,
gfx::Rect* rect) OVERRIDE;
virtual bool HasCompositionText() OVERRIDE;
- virtual bool GetTextRange(ui::Range* range) OVERRIDE;
- virtual bool GetCompositionTextRange(ui::Range* range) OVERRIDE;
- virtual bool GetSelectionRange(ui::Range* range) OVERRIDE;
- virtual bool SetSelectionRange(const ui::Range& range) OVERRIDE;
- virtual bool DeleteRange(const ui::Range& range) OVERRIDE;
- virtual bool GetTextFromRange(const ui::Range& range,
+ virtual bool GetTextRange(gfx::Range* range) OVERRIDE;
+ virtual bool GetCompositionTextRange(gfx::Range* range) OVERRIDE;
+ virtual bool GetSelectionRange(gfx::Range* range) 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;
virtual void OnInputMethodChanged() OVERRIDE;
virtual bool ChangeTextDirectionAndLayoutAlignment(
@@ -302,7 +301,8 @@ class RenderWidgetHostViewAura
virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE;
virtual bool HasHitTestMask() const OVERRIDE;
virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE;
- virtual scoped_refptr<ui::Texture> CopyTexture() OVERRIDE;
+ virtual void DidRecreateLayer(ui::Layer *old_layer,
+ ui::Layer *new_layer) OVERRIDE;
// Overridden from ui::EventHandler:
virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
@@ -329,6 +329,9 @@ class RenderWidgetHostViewAura
virtual void OnRootWindowHostMoved(const aura::RootWindow* root,
const gfx::Point& new_origin) OVERRIDE;
+ // FrameContainer implementation:
+ virtual void ReleaseCurrentFrame() OVERRIDE;
+
bool CanCopyToBitmap() const;
#if defined(OS_WIN)
@@ -340,25 +343,21 @@ class RenderWidgetHostViewAura
protected:
friend class RenderWidgetHostView;
+ virtual ~RenderWidgetHostViewAura();
- // Should construct only via RenderWidgetHostView::CreateViewForWidget.
+ // Should be constructed via RenderWidgetHostView::CreateViewForWidget.
explicit RenderWidgetHostViewAura(RenderWidgetHost* host);
RenderWidgetHostViewFrameSubscriber* frame_subscriber() const {
return frame_subscriber_.get();
}
- private:
- FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, SetCompositionText);
- FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, TouchEventState);
- FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, TouchEventSyncAsync);
+ virtual bool ShouldCreateResizeLock();
+ virtual scoped_ptr<ResizeLock> CreateResizeLock(bool defer_compositor_lock);
- class WindowObserver;
- friend class WindowObserver;
-#if defined(OS_WIN)
- class TransientWindowObserver;
- friend class TransientWindowObserver;
-#endif
+ // Exposed for tests.
+ aura::Window* window() { return window_; }
+ gfx::Size current_frame_size() const { return current_frame_size_; }
// Overridden from ui::CompositorObserver:
virtual void OnCompositingDidCommit(ui::Compositor* compositor) OVERRIDE;
@@ -372,6 +371,21 @@ class RenderWidgetHostViewAura
base::TimeTicks timebase,
base::TimeDelta interval) OVERRIDE;
+ private:
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, SetCompositionText);
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, TouchEventState);
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, TouchEventSyncAsync);
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, SwapNotifiesWindow);
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest,
+ SkippedDelegatedFrames);
+
+ class WindowObserver;
+ friend class WindowObserver;
+#if defined(OS_WIN)
+ class TransientWindowObserver;
+ friend class TransientWindowObserver;
+#endif
+
// Overridden from ImageTransportFactoryObserver:
virtual void OnLostResources() OVERRIDE;
@@ -387,8 +401,6 @@ class RenderWidgetHostViewAura
virtual gfx::Point GetLastTouchEventLocation() const OVERRIDE;
virtual void FatalAccessibilityTreeError() OVERRIDE;
- virtual ~RenderWidgetHostViewAura();
-
void UpdateCursorIfOverSelf();
bool ShouldSkipFrame(gfx::Size size_in_dip) const;
@@ -509,7 +521,9 @@ class RenderWidgetHostViewAura
scoped_ptr<cc::SoftwareFrameData> frame_data,
float frame_device_scale_factor,
const ui::LatencyInfo& latency_info);
- void SendSoftwareFrameAck(uint32 output_surface_id,
+ void SendSoftwareFrameAck(uint32 output_surface_id);
+ void SendReclaimSoftwareFrames();
+ void ReleaseSoftwareFrame(uint32 output_surface_id,
unsigned software_frame_id);
void DidReceiveFrameFromRenderer();
@@ -565,6 +579,8 @@ class RenderWidgetHostViewAura
// The current text input type.
ui::TextInputType text_input_type_;
+ // The current text input mode corresponding to HTML5 inputmode attribute.
+ ui::TextInputMode text_input_mode_;
bool can_compose_inline_;
// Rectangles for the selection anchor and focus.
@@ -588,12 +604,21 @@ class RenderWidgetHostViewAura
// This holds the current software framebuffer.
scoped_refptr<MemoryHolder> framebuffer_holder_;
+ // 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 damage in the previously presented buffer.
SkRegion previous_damage_;
// Pending damage from previous frames that we skipped.
SkRegion skipped_damage_;
+ // True after a delegated frame has been skipped, until a frame is not
+ // skipped.
+ bool skipped_frames_;
+
// 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.
@@ -625,9 +650,6 @@ class RenderWidgetHostViewAura
// software backing store is updated.
bool accelerated_compositing_state_changed_;
- // Used to prevent further resizes while a resize is pending.
- class ResizeLock;
-
// This lock is the one waiting for a frame of the right size to come back
// from the renderer/GPU process. It is set from the moment the aura window
// got resized, to the moment we committed the renderer frame of the same
@@ -700,6 +722,14 @@ class RenderWidgetHostViewAura
ui::LatencyInfo software_latency_info_;
+ struct ReleasedFrameInfo {
+ ReleasedFrameInfo(uint32 output_id, unsigned software_frame_id)
+ : output_surface_id(output_id), frame_id(software_frame_id) {}
+ uint32 output_surface_id;
+ unsigned frame_id;
+ };
+ std::vector<ReleasedFrameInfo> released_software_frames_;
+
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 03f7d5c591f..824db746ceb 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
@@ -5,16 +5,24 @@
#include "content/browser/renderer_host/render_widget_host_view_aura.h"
#include "base/basictypes.h"
+#include "base/memory/shared_memory.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h"
+#include "cc/output/compositor_frame.h"
+#include "cc/output/compositor_frame_metadata.h"
+#include "cc/output/gl_frame_data.h"
+#include "content/browser/aura/resize_lock.h"
+#include "content/browser/browser_thread_impl.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/common/gpu/gpu_messages.h"
#include "content/common/input_messages.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 "ipc/ipc_test_sink.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/env.h"
@@ -26,9 +34,11 @@
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
-#include "ui/base/events/event.h"
-#include "ui/base/events/event_utils.h"
#include "ui/base/ui_base_types.h"
+#include "ui/events/event.h"
+#include "ui/events/event_utils.h"
+
+using testing::_;
namespace content {
namespace {
@@ -69,11 +79,48 @@ class TestWindowObserver : public aura::WindowObserver {
DISALLOW_COPY_AND_ASSIGN(TestWindowObserver);
};
+class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura {
+ public:
+ FakeRenderWidgetHostViewAura(RenderWidgetHost* widget)
+ : RenderWidgetHostViewAura(widget), has_resize_lock_(false) {}
+
+ virtual ~FakeRenderWidgetHostViewAura() {}
+
+ virtual bool ShouldCreateResizeLock() OVERRIDE {
+ gfx::Size desired_size = window()->bounds().size();
+ return desired_size != current_frame_size();
+ }
+
+ virtual scoped_ptr<ResizeLock> CreateResizeLock(bool defer_compositor_lock)
+ OVERRIDE {
+ gfx::Size desired_size = window()->bounds().size();
+ return scoped_ptr<ResizeLock>(
+ new FakeResizeLock(desired_size, defer_compositor_lock));
+ }
+
+ void RunOnCompositingDidCommit() {
+ OnCompositingDidCommit(window()->GetRootWindow()->compositor());
+ }
+
+ // A lock that doesn't actually do anything to the compositor, and does not
+ // time out.
+ class FakeResizeLock : public ResizeLock {
+ public:
+ FakeResizeLock(const gfx::Size new_size, bool defer_compositor_lock)
+ : ResizeLock(new_size, defer_compositor_lock) {}
+ };
+
+ bool has_resize_lock_;
+ gfx::Size last_frame_size_;
+};
+
class RenderWidgetHostViewAuraTest : public testing::Test {
public:
- RenderWidgetHostViewAuraTest() {}
+ RenderWidgetHostViewAuraTest()
+ : browser_thread_for_ui_(BrowserThread::UI, &message_loop_) {}
virtual void SetUp() {
+ ImageTransportFactory::InitializeForUnitTests();
aura_test_helper_.reset(new aura::test::AuraTestHelper(&message_loop_));
aura_test_helper_->SetUp();
@@ -84,7 +131,7 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
sink_ = &process_host->sink();
parent_host_ = new RenderWidgetHostImpl(
- &delegate_, process_host, MSG_ROUTING_NONE);
+ &delegate_, process_host, MSG_ROUTING_NONE, false);
parent_view_ = static_cast<RenderWidgetHostViewAura*>(
RenderWidgetHostView::CreateViewForWidget(parent_host_));
parent_view_->InitAsChild(NULL);
@@ -92,10 +139,11 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
aura_test_helper_->root_window(), gfx::Rect());
widget_host_ = new RenderWidgetHostImpl(
- &delegate_, process_host, MSG_ROUTING_NONE);
+ &delegate_, process_host, MSG_ROUTING_NONE, false);
widget_host_->Init();
- view_ = static_cast<RenderWidgetHostViewAura*>(
- RenderWidgetHostView::CreateViewForWidget(widget_host_));
+ widget_host_->OnMessageReceived(
+ ViewHostMsg_DidActivateAcceleratedCompositing(0, true));
+ view_ = new FakeRenderWidgetHostViewAura(widget_host_);
}
virtual void TearDown() {
@@ -112,10 +160,12 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
message_loop_.DeleteSoon(FROM_HERE, browser_context_.release());
message_loop_.RunUntilIdle();
+ ImageTransportFactory::Terminate();
}
protected:
base::MessageLoopForUI message_loop_;
+ BrowserThreadImpl browser_thread_for_ui_;
scoped_ptr<aura::test::AuraTestHelper> aura_test_helper_;
scoped_ptr<BrowserContext> browser_context_;
MockRenderWidgetHostDelegate delegate_;
@@ -128,7 +178,7 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
// Tests should set these to NULL if they've already triggered their
// destruction.
RenderWidgetHostImpl* widget_host_;
- RenderWidgetHostViewAura* view_;
+ FakeRenderWidgetHostViewAura* view_;
IPC::TestSink* sink_;
@@ -170,6 +220,11 @@ class FullscreenLayoutManager : public aura::LayoutManager {
DISALLOW_COPY_AND_ASSIGN(FullscreenLayoutManager);
};
+class MockWindowObserver : public aura::WindowObserver {
+ public:
+ MOCK_METHOD2(OnWindowPaintScheduled, void(aura::Window*, const gfx::Rect&));
+};
+
} // namespace
// Checks that a fullscreen view has the correct show-state and receives the
@@ -231,7 +286,7 @@ TEST_F(RenderWidgetHostViewAuraTest, SetCompositionText) {
const ui::CompositionUnderlines& underlines = composition_text.underlines;
// Caret is at the end. (This emulates Japanese MSIME 2007 and later)
- composition_text.selection = ui::Range(4);
+ composition_text.selection = gfx::Range(4);
sink_->ClearMessages();
view_->SetCompositionText(composition_text);
@@ -584,4 +639,209 @@ TEST_F(RenderWidgetHostViewAuraTest, FullscreenResize) {
}
}
+scoped_ptr<cc::CompositorFrame> MakeGLFrame(float scale_factor,
+ gfx::Size size,
+ gfx::Rect damage) {
+ scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
+ frame->metadata.device_scale_factor = scale_factor;
+ frame->gl_frame_data.reset(new cc::GLFrameData);
+ frame->gl_frame_data->sync_point = 1;
+ memset(frame->gl_frame_data->mailbox.name, '1', 64);
+ frame->gl_frame_data->size = size;
+ frame->gl_frame_data->sub_buffer_rect = damage;
+ return frame.Pass();
+}
+
+scoped_ptr<cc::CompositorFrame> MakeSoftwareFrame(float scale_factor,
+ gfx::Size size,
+ gfx::Rect damage) {
+ scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
+ frame->metadata.device_scale_factor = scale_factor;
+ frame->software_frame_data.reset(new cc::SoftwareFrameData);
+ frame->software_frame_data->id = 1;
+ frame->software_frame_data->size = size;
+ frame->software_frame_data->damage_rect = damage;
+ base::SharedMemory shm;
+ shm.CreateAndMapAnonymous(size.GetArea() * 4);
+ shm.GiveToProcess(base::GetCurrentProcessHandle(),
+ &frame->software_frame_data->handle);
+ return frame.Pass();
+}
+
+scoped_ptr<cc::CompositorFrame> MakeDelegatedFrame(float scale_factor,
+ gfx::Size size,
+ gfx::Rect damage) {
+ scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
+ frame->metadata.device_scale_factor = scale_factor;
+ frame->delegated_frame_data.reset(new cc::DelegatedFrameData);
+
+ scoped_ptr<cc::RenderPass> pass = cc::RenderPass::Create();
+ pass->SetNew(cc::RenderPass::Id(1, 1),
+ gfx::Rect(size),
+ gfx::RectF(damage),
+ gfx::Transform());
+ frame->delegated_frame_data->render_pass_list.push_back(pass.Pass());
+ return frame.Pass();
+}
+
+// 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());
+ view_->SetSize(view_size);
+ view_->WasShown();
+
+ MockWindowObserver observer;
+ view_->window_->AddObserver(&observer);
+
+ // Swap a frame through the GPU path.
+ GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
+ params.surface_id = widget_host_->surface_id();
+ params.route_id = widget_host_->GetRoutingID();
+ params.mailbox_name = std::string(64, '1');
+ params.size = view_size;
+ params.scale_factor = 1.f;
+
+ EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
+ view_->AcceleratedSurfaceBuffersSwapped(params, 0);
+ testing::Mock::VerifyAndClearExpectations(&observer);
+
+ // DSF = 2
+ params.size = gfx::Size(200, 200);
+ params.scale_factor = 2.f;
+ EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
+ view_->AcceleratedSurfaceBuffersSwapped(params, 0);
+ testing::Mock::VerifyAndClearExpectations(&observer);
+
+ // Partial frames though GPU path
+ GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params post_params;
+ post_params.surface_id = widget_host_->surface_id();
+ post_params.route_id = widget_host_->GetRoutingID();
+ post_params.mailbox_name = std::string(64, '1');
+ post_params.surface_size = gfx::Size(200, 200);
+ post_params.surface_scale_factor = 2.f;
+ post_params.x = 40;
+ post_params.y = 40;
+ post_params.width = 80;
+ post_params.height = 80;
+ // rect from params is upside down, and is inflated in RWHVA, just because.
+ EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_,
+ gfx::Rect(19, 39, 42, 42)));
+ view_->AcceleratedSurfacePostSubBuffer(post_params, 0);
+ testing::Mock::VerifyAndClearExpectations(&observer);
+
+ // Composite-to-mailbox path
+ EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
+ view_->OnSwapCompositorFrame(0, MakeGLFrame(1.f, view_size, view_rect));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+
+ // rect from GL frame is upside down, and is inflated in RWHVA, just because.
+ EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_,
+ gfx::Rect(4, 89, 7, 7)));
+ view_->OnSwapCompositorFrame(
+ 0, MakeGLFrame(1.f, view_size, gfx::Rect(5, 5, 5, 5)));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+
+ // Software path
+ EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
+ view_->OnSwapCompositorFrame(0, MakeSoftwareFrame(1.f, view_size, view_rect));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+
+ EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_,
+ gfx::Rect(5, 5, 5, 5)));
+ view_->OnSwapCompositorFrame(
+ 0, MakeSoftwareFrame(1.f, view_size, gfx::Rect(5, 5, 5, 5)));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+
+ // Delegated renderer path
+ EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
+ view_->OnSwapCompositorFrame(
+ 0, MakeDelegatedFrame(1.f, view_size, view_rect));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+
+ EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_,
+ gfx::Rect(5, 5, 5, 5)));
+ view_->OnSwapCompositorFrame(
+ 0, MakeDelegatedFrame(1.f, view_size, gfx::Rect(5, 5, 5, 5)));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+
+ view_->window_->RemoveObserver(&observer);
+}
+
+// Skipped frames should not drop their damage.
+TEST_F(RenderWidgetHostViewAuraTest, SkippedDelegatedFrames) {
+ gfx::Rect view_rect(100, 100);
+ gfx::Size frame_size = view_rect.size();
+
+ view_->InitAsChild(NULL);
+ view_->GetNativeView()->SetDefaultParentByRootWindow(
+ parent_view_->GetNativeView()->GetRootWindow(), gfx::Rect());
+ view_->SetSize(view_rect.size());
+
+ MockWindowObserver observer;
+ view_->window_->AddObserver(&observer);
+
+ // A full frame of damage.
+ EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
+ view_->OnSwapCompositorFrame(
+ 0, MakeDelegatedFrame(1.f, frame_size, view_rect));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+ view_->RunOnCompositingDidCommit();
+
+ // A partial damage frame.
+ gfx::Rect partial_view_rect(30, 30, 20, 20);
+ EXPECT_CALL(observer,
+ OnWindowPaintScheduled(view_->window_, partial_view_rect));
+ view_->OnSwapCompositorFrame(
+ 0, MakeDelegatedFrame(1.f, frame_size, partial_view_rect));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+ view_->RunOnCompositingDidCommit();
+
+ // Lock the compositor. Now we should drop frames.
+ view_rect = gfx::Rect(150, 150);
+ view_->SetSize(view_rect.size());
+ view_->MaybeCreateResizeLock();
+
+ // This frame is dropped.
+ gfx::Rect dropped_damage_rect_1(10, 20, 30, 40);
+ EXPECT_CALL(observer, OnWindowPaintScheduled(_, _)).Times(0);
+ view_->OnSwapCompositorFrame(
+ 0, MakeDelegatedFrame(1.f, frame_size, dropped_damage_rect_1));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+ view_->RunOnCompositingDidCommit();
+
+ gfx::Rect dropped_damage_rect_2(40, 50, 10, 20);
+ EXPECT_CALL(observer, OnWindowPaintScheduled(_, _)).Times(0);
+ view_->OnSwapCompositorFrame(
+ 0, MakeDelegatedFrame(1.f, frame_size, dropped_damage_rect_2));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+ view_->RunOnCompositingDidCommit();
+
+ // Unlock the compositor. This frame should damage everything.
+ frame_size = view_rect.size();
+
+ gfx::Rect new_damage_rect(5, 6, 10, 10);
+ EXPECT_CALL(observer,
+ OnWindowPaintScheduled(view_->window_, view_rect));
+ view_->OnSwapCompositorFrame(
+ 0, MakeDelegatedFrame(1.f, frame_size, new_damage_rect));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+ view_->RunOnCompositingDidCommit();
+
+ // A partial damage frame, this should not be dropped.
+ EXPECT_CALL(observer,
+ OnWindowPaintScheduled(view_->window_, partial_view_rect));
+ view_->OnSwapCompositorFrame(
+ 0, MakeDelegatedFrame(1.f, frame_size, partial_view_rect));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+ view_->RunOnCompositingDidCommit();
+
+
+ view_->window_->RemoveObserver(&observer);
+}
+
} // 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 d6b1e789e2a..57181031f22 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
@@ -11,7 +11,7 @@
#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/smooth_scroll_gesture.h"
+#include "content/port/browser/synthetic_gesture.h"
#include "third_party/WebKit/public/web/WebScreenInfo.h"
#include "ui/gfx/display.h"
#include "ui/gfx/screen.h"
@@ -29,9 +29,9 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/common/content_switches.h"
-#include "ui/base/win/dpi.h"
-#include "ui/base/win/hwnd_util.h"
#include "ui/gfx/gdi_util.h"
+#include "ui/gfx/win/dpi.h"
+#include "ui/gfx/win/hwnd_util.h"
#endif
#if defined(TOOLKIT_GTK)
@@ -118,7 +118,7 @@ LRESULT CALLBACK PluginWrapperWindowProc(HWND window, unsigned int message,
}
bool IsPluginWrapperWindow(HWND window) {
- return ui::GetClassNameW(window) ==
+ return gfx::GetClassNameW(window) ==
string16(kWrapperNativeWindowClassName);
}
@@ -151,7 +151,7 @@ HWND ReparentWindow(HWND window, HWND parent) {
MAKEINTATOM(atom), 0,
WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
0, 0, 0, 0, parent, 0, instance, 0);
- ui::CheckWindowCreated(new_parent);
+ gfx::CheckWindowCreated(new_parent);
::SetParent(window, new_parent);
// How many times we try to find a PluginProcessHost whose process matches
// the HWND.
@@ -169,7 +169,7 @@ BOOL CALLBACK PaintEnumChildProc(HWND hwnd, LPARAM lparam) {
return TRUE;
gfx::Rect* rect = reinterpret_cast<gfx::Rect*>(lparam);
- gfx::Rect rect_in_pixels = ui::win::DIPToScreenRect(*rect);
+ gfx::Rect rect_in_pixels = gfx::win::DIPToScreenRect(*rect);
static UINT msg = RegisterWindowMessage(kPaintMessageName);
WPARAM wparam = MAKEWPARAM(rect_in_pixels.x(), rect_in_pixels.y());
lparam = MAKELPARAM(rect_in_pixels.width(), rect_in_pixels.height());
@@ -284,7 +284,7 @@ void RenderWidgetHostViewBase::MovePluginWindowsHelper(
#endif
if (move.rects_valid) {
- gfx::Rect clip_rect_in_pixel = ui::win::DIPToScreenRect(move.clip_rect);
+ gfx::Rect clip_rect_in_pixel = gfx::win::DIPToScreenRect(move.clip_rect);
HRGN hrgn = ::CreateRectRgn(clip_rect_in_pixel.x(),
clip_rect_in_pixel.y(),
clip_rect_in_pixel.right(),
@@ -313,7 +313,7 @@ void RenderWidgetHostViewBase::MovePluginWindowsHelper(
}
gfx::Rect window_rect_in_pixel =
- ui::win::DIPToScreenRect(move.window_rect);
+ gfx::win::DIPToScreenRect(move.window_rect);
defer_window_pos_info = ::DeferWindowPos(defer_window_pos_info,
window, NULL,
window_rect_in_pixel.x(),
@@ -382,7 +382,7 @@ RenderWidgetHostViewBase::RenderWidgetHostViewBase()
mouse_locked_(false),
showing_context_menu_(false),
selection_text_offset_(0),
- selection_range_(ui::Range::InvalidRange()),
+ selection_range_(gfx::Range::InvalidRange()),
current_device_scale_factor_(0),
renderer_frame_number_(0) {
}
@@ -417,7 +417,7 @@ float RenderWidgetHostViewBase::GetOverdrawBottomHeight() const {
void RenderWidgetHostViewBase::SelectionChanged(const string16& text,
size_t offset,
- const ui::Range& range) {
+ const gfx::Range& range) {
selection_text_ = text;
selection_text_offset_ = offset;
selection_range_.set_start(range.start());
@@ -501,13 +501,21 @@ bool RenderWidgetHostViewBase::HasDisplayPropertyChanged(gfx::NativeView view) {
return true;
}
-SmoothScrollGesture* RenderWidgetHostViewBase::CreateSmoothScrollGesture(
+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) {
}
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 68fcaffaea7..0472153b275 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
@@ -20,8 +20,8 @@
#include "base/callback_forward.h"
#include "content/common/content_export.h"
#include "content/port/browser/render_widget_host_view_port.h"
-#include "ui/base/range/range.h"
#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/range/range.h"
#include "ui/gfx/rect.h"
namespace content {
@@ -48,7 +48,7 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
virtual void SelectionChanged(const string16& text,
size_t offset,
- const ui::Range& range) OVERRIDE;
+ const gfx::Range& range) OVERRIDE;
virtual void SetBackground(const SkBitmap& background) OVERRIDE;
virtual const SkBitmap& GetBackground() OVERRIDE;
virtual gfx::Size GetPhysicalBackingSize() const OVERRIDE;
@@ -69,9 +69,12 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
GetBrowserAccessibilityManager() const OVERRIDE;
virtual void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
InputEventAckState ack_result) OVERRIDE;
- virtual SmoothScrollGesture* CreateSmoothScrollGesture(
+ 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 bool CanSubscribeFrame() const OVERRIDE;
virtual void BeginFrameSubscription(
scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) OVERRIDE;
@@ -144,7 +147,7 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
size_t selection_text_offset_;
// The current selection range relative to the start of the web page.
- ui::Range selection_range_;
+ gfx::Range selection_range_;
protected:
// The scale factor of the display the renderer is currently on.
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 2b47ff19315..0fe376e65b3 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
@@ -6,29 +6,30 @@
#include "base/message_loop/message_loop_proxy.h"
#include "base/path_service.h"
#include "base/run_loop.h"
+#include "content/browser/gpu/compositor_util.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/renderer_host/dip_util.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/render_widget_host_view_port.h"
-#include "content/public/browser/compositor_util.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test_utils.h"
-#include "content/shell/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
#include "media/base/video_frame.h"
#include "media/filters/skcanvas_video_renderer.h"
#include "net/base/net_util.h"
#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkBitmapDevice.h"
#include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/core/SkDevice.h"
#include "ui/base/ui_base_switches.h"
#include "ui/gfx/size_conversions.h"
+#include "ui/gfx/switches.h"
#include "ui/gl/gl_switches.h"
#if defined(OS_MACOSX)
@@ -36,7 +37,8 @@
#endif
#if defined(OS_WIN)
-#include "ui/base/win/dpi.h"
+#include "base/win/windows_version.h"
+#include "ui/gfx/win/dpi.h"
#endif
namespace content {
@@ -341,6 +343,14 @@ 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();
}
@@ -373,8 +383,18 @@ IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest,
// Tests that the callback passed to CopyFromCompositingSurfaceToVideoFrame is
// always called, even when the RenderWidgetHost is deleting in the middle of
// an async copy.
+//
+// Test is flaky on Win Aura. http://crbug.com/276783
+#if (defined(OS_WIN) && defined(USE_AURA)) || \
+ (defined(OS_CHROMEOS) && !defined(NDEBUG))
+#define MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete \
+ DISABLED_CopyFromCompositingSurface_CallbackDespiteDelete
+#else
+#define MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete \
+ CopyFromCompositingSurface_CallbackDespiteDelete
+#endif
IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest,
- CopyFromCompositingSurface_CallbackDespiteDelete) {
+ MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete) {
SET_UP_SURFACE_OR_PASS_TEST(NULL);
RenderWidgetHostViewPort* const view = GetRenderWidgetHostViewPort();
if (!view->CanCopyToVideoFrame()) {
@@ -410,6 +430,14 @@ 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()) {
@@ -435,6 +463,14 @@ 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()) {
@@ -558,7 +594,7 @@ class CompositingRenderWidgetHostViewBrowserTestTabCapture
bitmap.allocPixels();
bitmap.setIsOpaque(true);
- SkDevice device(bitmap);
+ SkBitmapDevice device(bitmap);
SkCanvas canvas(&device);
video_renderer.Paint(video_frame.get(),
@@ -638,7 +674,8 @@ class CompositingRenderWidgetHostViewBrowserTestTabCapture
// The page is loaded in the renderer, wait for a new frame to arrive.
uint32 frame = rwhvp->RendererFrameNumber();
- GetRenderWidgetHost()->ScheduleComposite();
+ while (!GetRenderWidgetHost()->ScheduleComposite())
+ GiveItSomeTime();
while (rwhvp->RendererFrameNumber() == frame)
GiveItSomeTime();
@@ -824,7 +861,7 @@ class CompositingRenderWidgetHostViewTabCaptureHighDPI
base::StringPrintf("%f", scale()));
#if defined(OS_WIN)
cmd->AppendSwitchASCII(switches::kHighDPISupport, "1");
- ui::EnableHighDPISupport();
+ gfx::EnableHighDPISupport();
#endif
}
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 ddaf9528cfd..61512ef7506 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
@@ -29,6 +29,7 @@
#include "content/browser/renderer_host/gtk_im_context_wrapper.h"
#include "content/browser/renderer_host/gtk_key_bindings_handler.h"
#include "content/browser/renderer_host/gtk_window_utils.h"
+#include "content/browser/renderer_host/input/web_input_event_builders_gtk.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/common/gpu/gpu_messages.h"
@@ -40,17 +41,15 @@
#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "third_party/WebKit/public/web/WebScreenInfo.h"
-#include "third_party/WebKit/public/web/gtk/WebInputEventFactory.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
-#include "ui/base/gtk/gtk_compat.h"
-#include "ui/base/text/text_elider.h"
#include "ui/base/x/active_window_watcher_x.h"
#include "ui/base/x/x11_util.h"
+#include "ui/gfx/gtk_compat.h"
#include "ui/gfx/gtk_native_view_id_manager.h"
#include "ui/gfx/gtk_preserve_window.h"
+#include "ui/gfx/text_elider.h"
#include "webkit/common/cursors/webcursor_gtk_data.h"
-using WebKit::WebInputEventFactory;
using WebKit::WebMouseWheelEvent;
using WebKit::WebScreenInfo;
@@ -70,10 +69,6 @@ namespace {
const int kMaxWindowWidth = 10000;
const int kMaxWindowHeight = 10000;
-// See WebInputEventFactor.cpp for a reason for this being the default
-// scroll size for linux.
-const float kDefaultScrollPixelsPerTick = 160.0f / 3.0f;
-
const GdkColor kBGColor =
#if defined(NDEBUG)
{ 0, 0xff * 257, 0xff * 257, 0xff * 257 };
@@ -354,7 +349,7 @@ class RenderWidgetHostViewGtkWidget {
RenderWidgetHostImpl* widget_host =
RenderWidgetHostImpl::From(host_view->GetRenderWidgetHost());
if (widget_host)
- widget_host->ForwardMouseEvent(WebInputEventFactory::mouseEvent(event));
+ widget_host->ForwardMouseEvent(WebMouseEventBuilder::Build(event));
// Although we did handle the mouse event, we need to let other handlers
// run (in particular the one installed by WebContentsViewGtk).
@@ -380,8 +375,7 @@ class RenderWidgetHostViewGtkWidget {
host_view->ModifyEventForEdgeDragging(widget, event);
- WebKit::WebMouseEvent mouse_event =
- WebInputEventFactory::mouseEvent(event);
+ WebKit::WebMouseEvent mouse_event = WebMouseEventBuilder::Build(event);
if (host_view->mouse_locked_) {
gfx::Point center = host_view->GetWidgetCenter();
@@ -431,8 +425,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 =
- WebInputEventFactory::mouseEvent(event);
+ WebKit::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
@@ -500,7 +493,7 @@ class RenderWidgetHostViewGtkWidget {
gdk_event_put(event);
gdk_event_free(event);
}
- return num_clicks * kDefaultScrollPixelsPerTick;
+ return num_clicks * WebMouseWheelEventBuilder::ScrollbarPixelsPerTick();
}
static gboolean OnMouseScrollEvent(GtkWidget* widget,
@@ -518,21 +511,23 @@ class RenderWidgetHostViewGtkWidget {
event->direction = GDK_SCROLL_RIGHT;
}
- WebMouseWheelEvent web_event = WebInputEventFactory::mouseWheelEvent(event);
+ WebMouseWheelEvent web_event = WebMouseWheelEventBuilder::Build(event);
+ const float pixelsPerTick =
+ WebMouseWheelEventBuilder::ScrollbarPixelsPerTick();
// We peek ahead at the top of the queue to look for additional pending
// scroll events.
if (event->direction == GDK_SCROLL_UP ||
event->direction == GDK_SCROLL_DOWN) {
if (event->direction == GDK_SCROLL_UP)
- web_event.deltaY = kDefaultScrollPixelsPerTick;
+ web_event.deltaY = pixelsPerTick;
else
- web_event.deltaY = -kDefaultScrollPixelsPerTick;
+ web_event.deltaY = -pixelsPerTick;
web_event.deltaY += GetPendingScrollDelta(true, event->state);
} else {
if (event->direction == GDK_SCROLL_LEFT)
- web_event.deltaX = kDefaultScrollPixelsPerTick;
+ web_event.deltaX = pixelsPerTick;
else
- web_event.deltaX = -kDefaultScrollPixelsPerTick;
+ web_event.deltaX = -pixelsPerTick;
web_event.deltaX += GetPendingScrollDelta(false, event->state);
}
RenderWidgetHostImpl::From(
@@ -546,7 +541,7 @@ class RenderWidgetHostViewGtkWidget {
RenderWidgetHostViewGtk::RenderWidgetHostViewGtk(RenderWidgetHost* widget_host)
: host_(RenderWidgetHostImpl::From(widget_host)),
about_to_validate_and_paint_(false),
- is_hidden_(false),
+ is_hidden_(host_->is_hidden()),
is_loading_(false),
parent_(NULL),
is_popup_first_mouse_release_(true),
@@ -686,17 +681,18 @@ RenderWidgetHost* RenderWidgetHostViewGtk::GetRenderWidgetHost() const {
}
void RenderWidgetHostViewGtk::WasShown() {
- if (!is_hidden_)
+ if (!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 (is_hidden_)
+ if (!host_ || is_hidden_)
return;
// If we receive any more paint messages while we are hidden, we want to
@@ -795,10 +791,12 @@ bool RenderWidgetHostViewGtk::IsSurfaceAvailableForCopy() const {
void RenderWidgetHostViewGtk::Show() {
gtk_widget_show(view_.get());
+ WasShown();
}
void RenderWidgetHostViewGtk::Hide() {
gtk_widget_hide(view_.get());
+ WasHidden();
}
bool RenderWidgetHostViewGtk::IsShowing() {
@@ -837,8 +835,8 @@ void RenderWidgetHostViewGtk::SetIsLoading(bool is_loading) {
void RenderWidgetHostViewGtk::TextInputTypeChanged(
ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) {
+ ui::TextInputMode input_mode,
+ bool can_compose_inline) {
im_context_->UpdateInputMethodState(type, can_compose_inline);
}
@@ -936,7 +934,7 @@ void RenderWidgetHostViewGtk::SetTooltipText(const string16& tooltip_text) {
// this itself).
// I filed https://bugzilla.gnome.org/show_bug.cgi?id=604641 upstream.
const string16 clamped_tooltip =
- ui::TruncateString(tooltip_text, kMaxTooltipLength);
+ gfx::TruncateString(tooltip_text, kMaxTooltipLength);
if (clamped_tooltip.empty()) {
gtk_widget_set_has_tooltip(view_.get(), FALSE);
@@ -948,7 +946,7 @@ void RenderWidgetHostViewGtk::SetTooltipText(const string16& tooltip_text) {
void RenderWidgetHostViewGtk::SelectionChanged(const string16& text,
size_t offset,
- const ui::Range& range) {
+ const gfx::Range& range) {
RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
if (text.empty() || range.is_empty())
@@ -1542,8 +1540,8 @@ void RenderWidgetHostViewGtk::FatalAccessibilityTreeError() {
}
}
-void RenderWidgetHostViewGtk::OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>& params) {
+void RenderWidgetHostViewGtk::OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>& params) {
if (!GetBrowserAccessibilityManager()) {
GtkWidget* parent = gtk_widget_get_parent(view_.get());
SetBrowserAccessibilityManager(
@@ -1552,7 +1550,7 @@ void RenderWidgetHostViewGtk::OnAccessibilityNotifications(
BrowserAccessibilityManagerGtk::GetEmptyDocument(),
this));
}
- GetBrowserAccessibilityManager()->OnAccessibilityNotifications(params);
+ GetBrowserAccessibilityManager()->OnAccessibilityEvents(params);
}
AtkObject* RenderWidgetHostViewGtk::GetAccessible() {
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 9ff410a07b1..fc57a1a5aad 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
@@ -17,8 +17,6 @@
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/common/content_export.h"
#include "ipc/ipc_sender.h"
-#include "ui/base/animation/animation_delegate.h"
-#include "ui/base/animation/slide_animation.h"
#include "ui/base/gtk/gtk_signal.h"
#include "ui/base/gtk/gtk_signal_registrar.h"
#include "ui/base/gtk/owned_widget_gtk.h"
@@ -83,8 +81,8 @@ class CONTENT_EXPORT RenderWidgetHostViewGtk
virtual void UpdateCursor(const WebCursor& cursor) OVERRIDE;
virtual void SetIsLoading(bool is_loading) OVERRIDE;
virtual void TextInputTypeChanged(ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) OVERRIDE;
+ ui::TextInputMode input_mode,
+ bool can_compose_inline) OVERRIDE;
virtual void ImeCancelComposition() OVERRIDE;
virtual void DidUpdateBackingStore(
const gfx::Rect& scroll_rect,
@@ -98,7 +96,7 @@ class CONTENT_EXPORT RenderWidgetHostViewGtk
virtual void SetTooltipText(const string16& tooltip_text) OVERRIDE;
virtual void SelectionChanged(const string16& text,
size_t offset,
- const ui::Range& range) OVERRIDE;
+ const gfx::Range& range) OVERRIDE;
virtual void SelectionBoundsChanged(
const ViewHostMsg_SelectionBounds_Params& params) OVERRIDE;
virtual void ScrollOffsetChanged() OVERRIDE;
@@ -131,8 +129,8 @@ class CONTENT_EXPORT RenderWidgetHostViewGtk
virtual gfx::GLSurfaceHandle GetCompositingSurface() OVERRIDE;
virtual bool LockMouse() OVERRIDE;
virtual void UnlockMouse() OVERRIDE;
- virtual void OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>& params)
+ virtual void OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>& params)
OVERRIDE;
// ActiveWindowWatcherXObserver implementation.
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 b49ca41054e..05730b92545 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
@@ -51,7 +51,7 @@ RenderWidgetHostViewGuest::RenderWidgetHostViewGuest(
RenderWidgetHostView* platform_view)
: host_(RenderWidgetHostImpl::From(widget_host)),
guest_(guest),
- is_hidden_(false),
+ 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));
@@ -289,11 +289,11 @@ void RenderWidgetHostViewGuest::SetIsLoading(bool is_loading) {
void RenderWidgetHostViewGuest::TextInputTypeChanged(
ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) {
+ ui::TextInputMode input_mode,
+ bool can_compose_inline) {
RenderWidgetHostViewPort::FromRWHV(
guest_->GetEmbedderRenderWidgetHostView())->
- TextInputTypeChanged(type, can_compose_inline, input_mode);
+ TextInputTypeChanged(type, input_mode, can_compose_inline);
}
void RenderWidgetHostViewGuest::ImeCancelComposition() {
@@ -302,7 +302,7 @@ void RenderWidgetHostViewGuest::ImeCancelComposition() {
#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
void RenderWidgetHostViewGuest::ImeCompositionRangeChanged(
- const ui::Range& range,
+ const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) {
}
#endif
@@ -317,7 +317,7 @@ void RenderWidgetHostViewGuest::DidUpdateBackingStore(
void RenderWidgetHostViewGuest::SelectionChanged(const string16& text,
size_t offset,
- const ui::Range& range) {
+ const gfx::Range& range) {
platform_view_->SelectionChanged(text, offset, range);
}
@@ -375,14 +375,6 @@ void RenderWidgetHostViewGuest::SetClickthroughRegion(SkRegion* region) {
}
#endif
-#if defined(OS_WIN) && defined(USE_AURA)
-gfx::NativeViewAccessible
-RenderWidgetHostViewGuest::AccessibleObjectFromChildId(long child_id) {
- NOTIMPLEMENTED();
- return NULL;
-}
-#endif
-
void RenderWidgetHostViewGuest::SetHasHorizontalScrollbar(
bool has_horizontal_scrollbar) {
platform_view_->SetHasHorizontalScrollbar(has_horizontal_scrollbar);
@@ -412,8 +404,8 @@ void RenderWidgetHostViewGuest::GetScreenInfo(WebKit::WebScreenInfo* results) {
embedder_view->GetScreenInfo(results);
}
-void RenderWidgetHostViewGuest::OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>& params) {
+void RenderWidgetHostViewGuest::OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>& params) {
}
#if defined(OS_MACOSX)
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 15b0acc1a8b..82f2eab1bac 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/events/event.h"
#include "ui/base/gestures/gesture_recognizer.h"
#include "ui/base/gestures/gesture_types.h"
+#include "ui/events/event.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/vector2d_f.h"
@@ -65,10 +65,6 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
#if defined(OS_WIN) && !defined(USE_AURA)
virtual void SetClickthroughRegion(SkRegion* region) OVERRIDE;
#endif
-#if defined(OS_WIN) && defined(USE_AURA)
- virtual gfx::NativeViewAccessible AccessibleObjectFromChildId(long child_id)
- OVERRIDE;
-#endif
// RenderWidgetHostViewPort implementation.
virtual void InitAsPopup(RenderWidgetHostView* parent_host_view,
@@ -85,12 +81,12 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
virtual void UpdateCursor(const WebCursor& cursor) OVERRIDE;
virtual void SetIsLoading(bool is_loading) OVERRIDE;
virtual void TextInputTypeChanged(ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) OVERRIDE;
+ 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 ui::Range& range,
+ const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) OVERRIDE;
#endif
virtual void DidUpdateBackingStore(
@@ -105,7 +101,7 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
virtual void SetTooltipText(const string16& tooltip_text) OVERRIDE;
virtual void SelectionChanged(const string16& text,
size_t offset,
- const ui::Range& range) OVERRIDE;
+ const gfx::Range& range) OVERRIDE;
virtual void SelectionBoundsChanged(
const ViewHostMsg_SelectionBounds_Params& params) OVERRIDE;
virtual void ScrollOffsetChanged() OVERRIDE;
@@ -146,8 +142,8 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
virtual bool LockMouse() OVERRIDE;
virtual void UnlockMouse() OVERRIDE;
virtual void GetScreenInfo(WebKit::WebScreenInfo* results) OVERRIDE;
- virtual void OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>&
+ virtual void OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>&
params) OVERRIDE;
#if defined(OS_MACOSX)
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 959f5e404a3..a112634b69d 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
@@ -32,7 +32,7 @@ class RenderWidgetHostViewGuestTest : public testing::Test {
MockRenderProcessHost* process_host =
new MockRenderProcessHost(browser_context_.get());
widget_host_ = new RenderWidgetHostImpl(
- &delegate_, process_host, MSG_ROUTING_NONE);
+ &delegate_, process_host, MSG_ROUTING_NONE, false);
view_ = new RenderWidgetHostViewGuest(
widget_host_, NULL, new TestRenderWidgetHostView(widget_host_));
}
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 6cbe6dc7b69..11b1d973a42 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
@@ -248,11 +248,11 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase,
virtual void UpdateCursor(const WebCursor& cursor) OVERRIDE;
virtual void SetIsLoading(bool is_loading) OVERRIDE;
virtual void TextInputTypeChanged(ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) OVERRIDE;
+ ui::TextInputMode input_mode,
+ bool can_compose_inline) OVERRIDE;
virtual void ImeCancelComposition() OVERRIDE;
virtual void ImeCompositionRangeChanged(
- const ui::Range& range,
+ const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) OVERRIDE;
virtual void DidUpdateBackingStore(
const gfx::Rect& scroll_rect,
@@ -265,7 +265,7 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase,
virtual void SetTooltipText(const string16& tooltip_text) OVERRIDE;
virtual void SelectionChanged(const string16& text,
size_t offset,
- const ui::Range& range) OVERRIDE;
+ const gfx::Range& range) OVERRIDE;
virtual void SelectionBoundsChanged(
const ViewHostMsg_SelectionBounds_Params& params) OVERRIDE;
virtual void ScrollOffsetChanged() OVERRIDE;
@@ -284,8 +284,8 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase,
scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) OVERRIDE;
virtual void EndFrameSubscription() OVERRIDE;
virtual void OnAcceleratedCompositingStateChange() OVERRIDE;
- virtual void OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>& params
+ virtual void OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>& params
) OVERRIDE;
virtual bool PostProcessEventForPluginIme(
const NativeWebKeyboardEvent& event) OVERRIDE;
@@ -354,19 +354,19 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase,
// point to |line_breaking_point|. The |line_break_point| is valid only if
// this function returns true.
bool GetLineBreakIndex(const std::vector<gfx::Rect>& bounds,
- const ui::Range& range,
+ const gfx::Range& range,
size_t* line_break_point);
// Returns composition character boundary rectangle. The |range| is
// composition based range. Also stores |actual_range| which is corresponding
// to actually used range for returned rectangle.
- gfx::Rect GetFirstRectForCompositionRange(const ui::Range& range,
- ui::Range* actual_range);
+ gfx::Rect GetFirstRectForCompositionRange(const gfx::Range& range,
+ gfx::Range* actual_range);
// Converts from given whole character range to composition oriented range. If
- // the conversion failed, return ui::Range::InvalidRange.
- ui::Range ConvertCharacterRangeToCompositionRange(
- const ui::Range& request_range);
+ // the conversion failed, return gfx::Range::InvalidRange.
+ gfx::Range ConvertCharacterRangeToCompositionRange(
+ const gfx::Range& request_range);
// These member variables should be private, but the associated ObjC class
// needs access to them and can't be made a friend.
@@ -548,7 +548,7 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase,
base::Time next_swap_ack_time_;
// The current composition character range and its bounds.
- ui::Range composition_range_;
+ gfx::Range composition_range_;
std::vector<gfx::Rect> composition_bounds_;
// The current caret bounds.
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_mac.mm b/chromium/content/browser/renderer_host/render_widget_host_view_mac.mm
index 07448884b5d..b6a6c180bdf 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
@@ -7,8 +7,9 @@
#import <objc/runtime.h>
#include <QuartzCore/QuartzCore.h>
+#include "base/basictypes.h"
#include "base/bind.h"
-#include "base/bind_helpers.h"
+#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/debug/crash_logging.h"
#include "base/debug/trace_event.h"
@@ -54,7 +55,7 @@
#include "ui/base/cocoa/animation_utils.h"
#import "ui/base/cocoa/fullscreen_window_manager.h"
#import "ui/base/cocoa/underlay_opengl_hosting_window.h"
-#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/base/layout.h"
#include "ui/gfx/display.h"
#include "ui/gfx/point.h"
@@ -425,7 +426,7 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget)
allow_overlapping_views_(false),
use_core_animation_(false),
is_loading_(false),
- is_hidden_(false),
+ is_hidden_(render_widget_host_->is_hidden()),
weak_factory_(this),
fullscreen_parent_host_view_(NULL),
pending_swap_buffers_acks_weak_factory_(this),
@@ -869,6 +870,10 @@ void RenderWidgetHostViewMac::Show() {
}
void RenderWidgetHostViewMac::Hide() {
+ // We're messing with the window, so do this to ensure no flashes.
+ if (!use_core_animation_)
+ [[cocoa_view_ window] disableScreenUpdatesUntilFlush];
+
[cocoa_view_ setHidden:YES];
WasHidden();
@@ -905,8 +910,8 @@ void RenderWidgetHostViewMac::SetIsLoading(bool is_loading) {
void RenderWidgetHostViewMac::TextInputTypeChanged(
ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) {
+ ui::TextInputMode input_mode,
+ bool can_compose_inline) {
if (text_input_type_ != type
|| can_compose_inline_ != can_compose_inline) {
text_input_type_ = type;
@@ -930,7 +935,7 @@ void RenderWidgetHostViewMac::ImeCancelComposition() {
}
void RenderWidgetHostViewMac::ImeCompositionRangeChanged(
- const ui::Range& range,
+ const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) {
// The RangeChanged message is only sent with valid values. The current
// caret position (start == end) will be sent if there is no IME range.
@@ -1074,7 +1079,7 @@ void RenderWidgetHostViewMac::StopSpeaking() {
//
void RenderWidgetHostViewMac::SelectionChanged(const string16& text,
size_t offset,
- const ui::Range& range) {
+ const gfx::Range& range) {
if (range.is_empty() || text.empty()) {
selected_text_.clear();
} else {
@@ -1161,7 +1166,7 @@ void RenderWidgetHostViewMac::CopyFromCompositingSurface(
gfx::Size dst_pixel_size = gfx::ToFlooredSize(
gfx::ScaleSize(dst_size, scale));
- scoped_callback_runner.Release();
+ ignore_result(scoped_callback_runner.Release());
compositing_iosurface_->CopyTo(GetScaledOpenGLPixelRect(src_subrect),
dst_pixel_size,
@@ -1192,7 +1197,7 @@ void RenderWidgetHostViewMac::CopyFromCompositingSurfaceToVideoFrame(
if (src_subrect.IsEmpty())
return;
- scoped_callback_runner.Release();
+ ignore_result(scoped_callback_runner.Release());
compositing_iosurface_->CopyToVideoFrame(
GetScaledOpenGLPixelRect(src_subrect),
target,
@@ -1485,7 +1490,7 @@ void RenderWidgetHostViewMac::GetVSyncParameters(
bool RenderWidgetHostViewMac::GetLineBreakIndex(
const std::vector<gfx::Rect>& bounds,
- const ui::Range& range,
+ const gfx::Range& range,
size_t* line_break_point) {
DCHECK(line_break_point);
if (range.start() >= bounds.size() || range.is_reversed() || range.is_empty())
@@ -1515,8 +1520,8 @@ bool RenderWidgetHostViewMac::GetLineBreakIndex(
}
gfx::Rect RenderWidgetHostViewMac::GetFirstRectForCompositionRange(
- const ui::Range& range,
- ui::Range* actual_range) {
+ const gfx::Range& range,
+ gfx::Range* actual_range) {
DCHECK(actual_range);
DCHECK(!composition_bounds_.empty());
DCHECK(range.start() <= composition_bounds_.size());
@@ -1541,7 +1546,7 @@ gfx::Rect RenderWidgetHostViewMac::GetFirstRectForCompositionRange(
if (!GetLineBreakIndex(composition_bounds_, range, &end_idx)) {
end_idx = range.end();
}
- *actual_range = ui::Range(range.start(), end_idx);
+ *actual_range = gfx::Range(range.start(), end_idx);
gfx::Rect rect = composition_bounds_[range.start()];
for (size_t i = range.start() + 1; i < end_idx; ++i) {
rect.Union(composition_bounds_[i]);
@@ -1549,21 +1554,21 @@ gfx::Rect RenderWidgetHostViewMac::GetFirstRectForCompositionRange(
return rect;
}
-ui::Range RenderWidgetHostViewMac::ConvertCharacterRangeToCompositionRange(
- const ui::Range& request_range) {
+gfx::Range RenderWidgetHostViewMac::ConvertCharacterRangeToCompositionRange(
+ const gfx::Range& request_range) {
if (composition_range_.is_empty())
- return ui::Range::InvalidRange();
+ return gfx::Range::InvalidRange();
if (request_range.is_reversed())
- return ui::Range::InvalidRange();
+ return gfx::Range::InvalidRange();
if (request_range.start() < composition_range_.start() ||
request_range.start() > composition_range_.end() ||
request_range.end() > composition_range_.end()) {
- return ui::Range::InvalidRange();
+ return gfx::Range::InvalidRange();
}
- return ui::Range(
+ return gfx::Range(
request_range.start() - composition_range_.start(),
request_range.end() - composition_range_.start());
}
@@ -1578,16 +1583,16 @@ bool RenderWidgetHostViewMac::GetCachedFirstRectForCharacterRange(
"RenderWidgetHostViewMac::GetFirstRectForCharacterRange");
// If requested range is same as caret location, we can just return it.
- if (selection_range_.is_empty() && ui::Range(range) == selection_range_) {
+ if (selection_range_.is_empty() && gfx::Range(range) == selection_range_) {
if (actual_range)
*actual_range = range;
*rect = NSRectFromCGRect(caret_rect_.ToCGRect());
return true;
}
- const ui::Range request_range_in_composition =
- ConvertCharacterRangeToCompositionRange(ui::Range(range));
- if (request_range_in_composition == ui::Range::InvalidRange())
+ const gfx::Range request_range_in_composition =
+ ConvertCharacterRangeToCompositionRange(gfx::Range(range));
+ if (request_range_in_composition == gfx::Range::InvalidRange())
return false;
// If firstRectForCharacterRange in WebFrame is failed in renderer,
@@ -1596,12 +1601,12 @@ bool RenderWidgetHostViewMac::GetCachedFirstRectForCharacterRange(
return false;
DCHECK_EQ(composition_bounds_.size(), composition_range_.length());
- ui::Range ui_actual_range;
+ gfx::Range ui_actual_range;
*rect = NSRectFromCGRect(GetFirstRectForCompositionRange(
request_range_in_composition,
&ui_actual_range).ToCGRect());
if (actual_range) {
- *actual_range = ui::Range(
+ *actual_range = gfx::Range(
composition_range_.start() + ui_actual_range.start(),
composition_range_.start() + ui_actual_range.end()).ToNSRange();
}
@@ -1787,6 +1792,10 @@ void RenderWidgetHostViewMac::GotSoftwareFrame() {
// Also note that it is necessary that clearDrawable be called if
// overlapping views are not allowed, e.g, for content shell.
// http://crbug.com/178408
+ // Disable screen updates so that the changes of flashes is minimized.
+ // http://crbug.com/279472
+ if (!use_core_animation_)
+ [[cocoa_view_ window] disableScreenUpdatesUntilFlush];
if (allow_overlapping_views_)
DestroyCompositedIOSurfaceAndLayer(kLeaveContextBoundToView);
else
@@ -1853,8 +1862,8 @@ void RenderWidgetHostViewMac::SetBackground(const SkBitmap& background) {
render_widget_host_->GetRoutingID(), background));
}
-void RenderWidgetHostViewMac::OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>& params) {
+void RenderWidgetHostViewMac::OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>& params) {
if (!GetBrowserAccessibilityManager()) {
SetBrowserAccessibilityManager(
new BrowserAccessibilityManagerMac(
@@ -1862,7 +1871,7 @@ void RenderWidgetHostViewMac::OnAccessibilityNotifications(
BrowserAccessibilityManagerMac::GetEmptyDocument(),
NULL));
}
- GetBrowserAccessibilityManager()->OnAccessibilityNotifications(params);
+ GetBrowserAccessibilityManager()->OnAccessibilityEvents(params);
}
void RenderWidgetHostViewMac::SetTextInputActive(bool active) {
@@ -2325,7 +2334,7 @@ void RenderWidgetHostViewMac::FrameSwapped() {
if (textToBeInserted_.length() >
((hasMarkedText_ || oldHasMarkedText) ? 0u : 1u)) {
widgetHost->ImeConfirmComposition(
- textToBeInserted_, ui::Range::InvalidRange(), false);
+ textToBeInserted_, gfx::Range::InvalidRange(), false);
textInserted = YES;
}
@@ -2342,7 +2351,7 @@ void RenderWidgetHostViewMac::FrameSwapped() {
} else if (oldHasMarkedText && !hasMarkedText_ && !textInserted) {
if (unmarkTextCalled_) {
widgetHost->ImeConfirmComposition(
- string16(), ui::Range::InvalidRange(), false);
+ string16(), gfx::Range::InvalidRange(), false);
} else {
widgetHost->ImeCancelComposition();
}
@@ -3422,7 +3431,7 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
// called in keyEvent: method.
if (!handlingKeyDown_) {
renderWidgetHostView_->render_widget_host_->ImeConfirmComposition(
- string16(), ui::Range::InvalidRange(), false);
+ string16(), gfx::Range::InvalidRange(), false);
} else {
unmarkTextCalled_ = YES;
}
@@ -3515,7 +3524,7 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
if (handlingKeyDown_) {
textToBeInserted_.append(base::SysNSStringToUTF16(im_text));
} else {
- ui::Range replacement_range(replacementRange);
+ gfx::Range replacement_range(replacementRange);
renderWidgetHostView_->render_widget_host_->ImeConfirmComposition(
base::SysNSStringToUTF16(im_text), replacement_range, false);
}
@@ -3660,7 +3669,7 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
if (renderWidgetHostView_->render_widget_host_)
renderWidgetHostView_->render_widget_host_->ImeConfirmComposition(
- string16(), ui::Range::InvalidRange(), false);
+ string16(), gfx::Range::InvalidRange(), false);
[self cancelComposition];
}
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm b/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
index 0d3ee0a8aa0..ba92843ebf7 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
@@ -78,7 +78,7 @@ class RenderWidgetHostEditCommandCounter : public RenderWidgetHostImpl {
RenderWidgetHostDelegate* delegate,
RenderProcessHost* process,
int routing_id)
- : RenderWidgetHostImpl(delegate, process, routing_id),
+ : RenderWidgetHostImpl(delegate, process, routing_id, false),
edit_command_message_count_(0) {
}
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 3c91bc6abdf..7a152d18da8 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
@@ -101,7 +101,7 @@ class MockRenderWidgetHostImpl : public RenderWidgetHostImpl {
MockRenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
RenderProcessHost* process,
int routing_id)
- : RenderWidgetHostImpl(delegate, process, routing_id) {
+ : RenderWidgetHostImpl(delegate, process, routing_id, false) {
}
MOCK_METHOD0(Focus, void());
@@ -140,7 +140,7 @@ void GenerateCompositionRectArray(const gfx::Point& origin,
gfx::Rect GetExpectedRect(const gfx::Point& origin,
const gfx::Size& size,
- const ui::Range& range,
+ const gfx::Range& range,
int line_no) {
return gfx::Rect(
origin.x() + range.start() * size.width(),
@@ -264,7 +264,7 @@ TEST_F(RenderWidgetHostViewMacTest, FullscreenCloseOnEscape) {
new MockRenderProcessHost(&browser_context);
// Owned by its |cocoa_view()|.
RenderWidgetHostImpl* rwh = new RenderWidgetHostImpl(
- &delegate, process_host, MSG_ROUTING_NONE);
+ &delegate, process_host, MSG_ROUTING_NONE, false);
RenderWidgetHostViewMac* view = static_cast<RenderWidgetHostViewMac*>(
RenderWidgetHostView::CreateViewForWidget(rwh));
@@ -298,7 +298,7 @@ TEST_F(RenderWidgetHostViewMacTest, AcceleratorDestroy) {
new MockRenderProcessHost(&browser_context);
// Owned by its |cocoa_view()|.
RenderWidgetHostImpl* rwh = new RenderWidgetHostImpl(
- &delegate, process_host, MSG_ROUTING_NONE);
+ &delegate, process_host, MSG_ROUTING_NONE, false);
RenderWidgetHostViewMac* view = static_cast<RenderWidgetHostViewMac*>(
RenderWidgetHostView::CreateViewForWidget(rwh));
@@ -322,7 +322,7 @@ TEST_F(RenderWidgetHostViewMacTest, GetFirstRectForCharacterRangeCaretCase) {
const size_t kDummyOffset = 0;
gfx::Rect caret_rect(10, 11, 0, 10);
- ui::Range caret_range(0, 0);
+ gfx::Range caret_range(0, 0);
ViewHostMsg_SelectionBounds_Params params;
NSRect rect;
@@ -336,24 +336,24 @@ TEST_F(RenderWidgetHostViewMacTest, GetFirstRectForCharacterRangeCaretCase) {
&rect,
&actual_range));
EXPECT_EQ(caret_rect, gfx::Rect(NSRectToCGRect(rect)));
- EXPECT_EQ(caret_range, ui::Range(actual_range));
+ EXPECT_EQ(caret_range, gfx::Range(actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(0, 1).ToNSRange(),
+ gfx::Range(0, 1).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(1, 1).ToNSRange(),
+ gfx::Range(1, 1).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(2, 3).ToNSRange(),
+ gfx::Range(2, 3).ToNSRange(),
&rect,
&actual_range));
// Caret moved.
caret_rect = gfx::Rect(20, 11, 0, 10);
- caret_range = ui::Range(1, 1);
+ caret_range = gfx::Range(1, 1);
params.anchor_rect = params.focus_rect = caret_rect;
rwhv_mac_->SelectionChanged(kDummyString, kDummyOffset, caret_range);
rwhv_mac_->SelectionBoundsChanged(params);
@@ -362,45 +362,45 @@ TEST_F(RenderWidgetHostViewMacTest, GetFirstRectForCharacterRangeCaretCase) {
&rect,
&actual_range));
EXPECT_EQ(caret_rect, gfx::Rect(NSRectToCGRect(rect)));
- EXPECT_EQ(caret_range, ui::Range(actual_range));
+ EXPECT_EQ(caret_range, gfx::Range(actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(0, 0).ToNSRange(),
+ gfx::Range(0, 0).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(1, 2).ToNSRange(),
+ gfx::Range(1, 2).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(2, 3).ToNSRange(),
+ gfx::Range(2, 3).ToNSRange(),
&rect,
&actual_range));
// No caret.
- caret_range = ui::Range(1, 2);
+ caret_range = gfx::Range(1, 2);
rwhv_mac_->SelectionChanged(kDummyString, kDummyOffset, caret_range);
params.anchor_rect = caret_rect;
params.focus_rect = gfx::Rect(30, 11, 0, 10);
rwhv_mac_->SelectionBoundsChanged(params);
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(0, 0).ToNSRange(),
+ gfx::Range(0, 0).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(0, 1).ToNSRange(),
+ gfx::Range(0, 1).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(1, 1).ToNSRange(),
+ gfx::Range(1, 1).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(1, 2).ToNSRange(),
+ gfx::Range(1, 2).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(2, 2).ToNSRange(),
+ gfx::Range(2, 2).ToNSRange(),
&rect,
&actual_range));
}
@@ -412,46 +412,46 @@ TEST_F(RenderWidgetHostViewMacTest, UpdateCompositionSinglelineCase) {
NSRect rect;
// Make sure not crashing by passing NULL pointer instead of |actual_range|.
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(0, 0).ToNSRange(),
+ gfx::Range(0, 0).ToNSRange(),
&rect,
NULL));
// If there are no update from renderer, always returned caret position.
NSRange actual_range;
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(0, 0).ToNSRange(),
+ gfx::Range(0, 0).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(0, 1).ToNSRange(),
+ gfx::Range(0, 1).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(1, 0).ToNSRange(),
+ gfx::Range(1, 0).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(1, 1).ToNSRange(),
+ gfx::Range(1, 1).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(1, 2).ToNSRange(),
+ gfx::Range(1, 2).ToNSRange(),
&rect,
&actual_range));
// If the firstRectForCharacterRange is failed in renderer, empty rect vector
// is sent. Make sure this does not crash.
- rwhv_mac_->ImeCompositionRangeChanged(ui::Range(10, 12),
+ rwhv_mac_->ImeCompositionRangeChanged(gfx::Range(10, 12),
std::vector<gfx::Rect>());
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(10, 11).ToNSRange(),
+ gfx::Range(10, 11).ToNSRange(),
&rect,
NULL));
const int kCompositionLength = 10;
std::vector<gfx::Rect> composition_bounds;
const int kCompositionStart = 3;
- const ui::Range kCompositionRange(kCompositionStart,
+ const gfx::Range kCompositionRange(kCompositionStart,
kCompositionStart + kCompositionLength);
GenerateCompositionRectArray(kOrigin,
kBoundsUnit,
@@ -462,45 +462,45 @@ TEST_F(RenderWidgetHostViewMacTest, UpdateCompositionSinglelineCase) {
// Out of range requests will return caret position.
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(0, 0).ToNSRange(),
+ gfx::Range(0, 0).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(1, 1).ToNSRange(),
+ gfx::Range(1, 1).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(1, 2).ToNSRange(),
+ gfx::Range(1, 2).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(2, 2).ToNSRange(),
+ gfx::Range(2, 2).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(13, 14).ToNSRange(),
+ gfx::Range(13, 14).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(14, 15).ToNSRange(),
+ gfx::Range(14, 15).ToNSRange(),
&rect,
&actual_range));
for (int i = 0; i <= kCompositionLength; ++i) {
for (int j = 0; j <= kCompositionLength - i; ++j) {
- const ui::Range range(i, i + j);
+ const gfx::Range range(i, i + j);
const gfx::Rect expected_rect = GetExpectedRect(kOrigin,
kBoundsUnit,
range,
0);
- const NSRange request_range = ui::Range(
+ const NSRange request_range = gfx::Range(
kCompositionStart + range.start(),
kCompositionStart + range.end()).ToNSRange();
EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
request_range,
&rect,
&actual_range));
- EXPECT_EQ(ui::Range(request_range), ui::Range(actual_range));
+ EXPECT_EQ(gfx::Range(request_range), gfx::Range(actual_range));
EXPECT_EQ(expected_rect, gfx::Rect(NSRectToCGRect(rect)));
// Make sure not crashing by passing NULL pointer instead of
@@ -520,7 +520,7 @@ TEST_F(RenderWidgetHostViewMacTest, UpdateCompositionMultilineCase) {
const int kCompositionLength = 30;
std::vector<gfx::Rect> composition_bounds;
- const ui::Range kCompositionRange(0, kCompositionLength);
+ const gfx::Range kCompositionRange(0, kCompositionLength);
// Set breaking point at 10 and 20.
std::vector<size_t> break_points;
break_points.push_back(10);
@@ -533,113 +533,113 @@ TEST_F(RenderWidgetHostViewMacTest, UpdateCompositionMultilineCase) {
rwhv_mac_->ImeCompositionRangeChanged(kCompositionRange, composition_bounds);
// Range doesn't contain line breaking point.
- ui::Range range;
- range = ui::Range(5, 8);
+ gfx::Range range;
+ range = gfx::Range(5, 8);
NSRange actual_range;
EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(),
&rect,
&actual_range));
- EXPECT_EQ(range, ui::Range(actual_range));
+ EXPECT_EQ(range, gfx::Range(actual_range));
EXPECT_EQ(
GetExpectedRect(kOrigin, kBoundsUnit, range, 0),
gfx::Rect(NSRectToCGRect(rect)));
- range = ui::Range(15, 18);
+ range = gfx::Range(15, 18);
EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(),
&rect,
&actual_range));
- EXPECT_EQ(range, ui::Range(actual_range));
+ EXPECT_EQ(range, gfx::Range(actual_range));
EXPECT_EQ(
- GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(5, 8), 1),
+ GetExpectedRect(kOrigin, kBoundsUnit, gfx::Range(5, 8), 1),
gfx::Rect(NSRectToCGRect(rect)));
- range = ui::Range(25, 28);
+ range = gfx::Range(25, 28);
EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(),
&rect,
&actual_range));
- EXPECT_EQ(range, ui::Range(actual_range));
+ EXPECT_EQ(range, gfx::Range(actual_range));
EXPECT_EQ(
- GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(5, 8), 2),
+ GetExpectedRect(kOrigin, kBoundsUnit, gfx::Range(5, 8), 2),
gfx::Rect(NSRectToCGRect(rect)));
// Range contains line breaking point.
- range = ui::Range(8, 12);
+ range = gfx::Range(8, 12);
EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(),
&rect,
&actual_range));
- EXPECT_EQ(ui::Range(8, 10), ui::Range(actual_range));
+ EXPECT_EQ(gfx::Range(8, 10), gfx::Range(actual_range));
EXPECT_EQ(
- GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(8, 10), 0),
+ GetExpectedRect(kOrigin, kBoundsUnit, gfx::Range(8, 10), 0),
gfx::Rect(NSRectToCGRect(rect)));
- range = ui::Range(18, 22);
+ range = gfx::Range(18, 22);
EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(),
&rect,
&actual_range));
- EXPECT_EQ(ui::Range(18, 20), ui::Range(actual_range));
+ EXPECT_EQ(gfx::Range(18, 20), gfx::Range(actual_range));
EXPECT_EQ(
- GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(8, 10), 1),
+ GetExpectedRect(kOrigin, kBoundsUnit, gfx::Range(8, 10), 1),
gfx::Rect(NSRectToCGRect(rect)));
// Start point is line breaking point.
- range = ui::Range(10, 12);
+ range = gfx::Range(10, 12);
EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(),
&rect,
&actual_range));
- EXPECT_EQ(ui::Range(10, 12), ui::Range(actual_range));
+ EXPECT_EQ(gfx::Range(10, 12), gfx::Range(actual_range));
EXPECT_EQ(
- GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(0, 2), 1),
+ GetExpectedRect(kOrigin, kBoundsUnit, gfx::Range(0, 2), 1),
gfx::Rect(NSRectToCGRect(rect)));
- range = ui::Range(20, 22);
+ range = gfx::Range(20, 22);
EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(),
&rect,
&actual_range));
- EXPECT_EQ(ui::Range(20, 22), ui::Range(actual_range));
+ EXPECT_EQ(gfx::Range(20, 22), gfx::Range(actual_range));
EXPECT_EQ(
- GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(0, 2), 2),
+ GetExpectedRect(kOrigin, kBoundsUnit, gfx::Range(0, 2), 2),
gfx::Rect(NSRectToCGRect(rect)));
// End point is line breaking point.
- range = ui::Range(5, 10);
+ range = gfx::Range(5, 10);
EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(),
&rect,
&actual_range));
- EXPECT_EQ(ui::Range(5, 10), ui::Range(actual_range));
+ EXPECT_EQ(gfx::Range(5, 10), gfx::Range(actual_range));
EXPECT_EQ(
- GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(5, 10), 0),
+ GetExpectedRect(kOrigin, kBoundsUnit, gfx::Range(5, 10), 0),
gfx::Rect(NSRectToCGRect(rect)));
- range = ui::Range(15, 20);
+ range = gfx::Range(15, 20);
EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(),
&rect,
&actual_range));
- EXPECT_EQ(ui::Range(15, 20), ui::Range(actual_range));
+ EXPECT_EQ(gfx::Range(15, 20), gfx::Range(actual_range));
EXPECT_EQ(
- GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(5, 10), 1),
+ GetExpectedRect(kOrigin, kBoundsUnit, gfx::Range(5, 10), 1),
gfx::Rect(NSRectToCGRect(rect)));
// Start and end point are same line breaking point.
- range = ui::Range(10, 10);
+ range = gfx::Range(10, 10);
EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(),
&rect,
&actual_range));
- EXPECT_EQ(ui::Range(10, 10), ui::Range(actual_range));
+ EXPECT_EQ(gfx::Range(10, 10), gfx::Range(actual_range));
EXPECT_EQ(
- GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(0, 0), 1),
+ GetExpectedRect(kOrigin, kBoundsUnit, gfx::Range(0, 0), 1),
gfx::Rect(NSRectToCGRect(rect)));
- range = ui::Range(20, 20);
+ range = gfx::Range(20, 20);
EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(),
&rect,
&actual_range));
- EXPECT_EQ(ui::Range(20, 20), ui::Range(actual_range));
+ EXPECT_EQ(gfx::Range(20, 20), gfx::Range(actual_range));
EXPECT_EQ(
- GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(0, 0), 2),
+ GetExpectedRect(kOrigin, kBoundsUnit, gfx::Range(0, 0), 2),
gfx::Rect(NSRectToCGRect(rect)));
// Start and end point are different line breaking point.
- range = ui::Range(10, 20);
+ range = gfx::Range(10, 20);
EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(),
&rect,
&actual_range));
- EXPECT_EQ(ui::Range(10, 20), ui::Range(actual_range));
+ EXPECT_EQ(gfx::Range(10, 20), gfx::Range(actual_range));
EXPECT_EQ(
- GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(0, 10), 1),
+ GetExpectedRect(kOrigin, kBoundsUnit, gfx::Range(0, 10), 1),
gfx::Rect(NSRectToCGRect(rect)));
}
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 a6ee28b0189..de2aa656a0d 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
@@ -12,8 +12,9 @@
#include <map>
#include <stack>
+#include "base/basictypes.h"
#include "base/bind.h"
-#include "base/bind_helpers.h"
+#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/i18n/rtl.h"
@@ -56,25 +57,26 @@
#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "third_party/skia/include/core/SkRegion.h"
-#include "ui/base/events/event.h"
-#include "ui/base/events/event_utils.h"
#include "ui/base/ime/composition_text.h"
#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/text/text_elider.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"
#include "ui/base/view_prop.h"
-#include "ui/base/win/dpi.h"
-#include "ui/base/win/hwnd_util.h"
#include "ui/base/win/mouse_wheel_util.h"
#include "ui/base/win/touch_input.h"
+#include "ui/events/event.h"
+#include "ui/events/event_utils.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/rect_conversions.h"
#include "ui/gfx/screen.h"
+#include "ui/gfx/text_elider.h"
+#include "ui/gfx/win/dpi.h"
+#include "ui/gfx/win/hwnd_util.h"
#include "webkit/common/cursors/webcursor.h"
#include "win8/util/win8_util.h"
@@ -312,7 +314,7 @@ void GetScreenInfoForWindow(gfx::NativeViewId id,
MONITORINFOEX monitor_info;
monitor_info.cbSize = sizeof(MONITORINFOEX);
- if (!GetMonitorInfo(monitor, &monitor_info))
+ if (!base::win::GetMonitorInfoWrapper(monitor, &monitor_info))
return;
DEVMODE dev_mode;
@@ -323,7 +325,7 @@ void GetScreenInfoForWindow(gfx::NativeViewId id,
WebKit::WebScreenInfo screen_info;
screen_info.depth = dev_mode.dmBitsPerPel;
screen_info.depthPerComponent = dev_mode.dmBitsPerPel / 3; // Assumes RGB
- screen_info.deviceScaleFactor = ui::win::GetDeviceScaleFactor();
+ screen_info.deviceScaleFactor = gfx::win::GetDeviceScaleFactor();
screen_info.isMonochrome = dev_mode.dmColor == DMCOLOR_MONOCHROME;
screen_info.rect = gfx::Rect(monitor_info.rcMonitor);
screen_info.availableRect = gfx::Rect(monitor_info.rcWork);
@@ -355,8 +357,6 @@ class WebTouchState {
bool is_changed() { return touch_event_.changedTouchesLength != 0; }
private:
- typedef std::map<unsigned int, int> MapType;
-
// Adds a touch point or returns NULL if there's not enough space.
WebKit::WebTouchPoint* AddTouchPoint(TOUCHINPUT* touch_input);
@@ -374,9 +374,7 @@ class WebTouchState {
WebKit::WebTouchEvent touch_event_;
const RenderWidgetHostViewWin* const window_;
- // Maps OS touch Id's into an internal (WebKit-friendly) touch-id.
- // WebKit expects small consecutive integers, starting at 0.
- MapType touch_map_;
+ ui::SequentialIDGenerator id_generator_;
DISALLOW_COPY_AND_ASSIGN(WebTouchState);
};
@@ -395,7 +393,7 @@ RenderWidgetHostViewWin::RenderWidgetHostViewWin(RenderWidgetHost* widget)
imm32_manager_(new ui::IMM32Manager),
ime_notification_(false),
capture_enter_key_(false),
- is_hidden_(false),
+ is_hidden_(render_widget_host_->is_hidden()),
about_to_validate_and_paint_(false),
close_on_deactivate_(false),
being_destroyed_(false),
@@ -408,7 +406,7 @@ RenderWidgetHostViewWin::RenderWidgetHostViewWin(RenderWidgetHost* widget)
can_compose_inline_(true),
is_fullscreen_(false),
ignore_mouse_movement_(true),
- composition_range_(ui::Range::InvalidRange()),
+ composition_range_(gfx::Range::InvalidRange()),
touch_state_(new WebTouchState(this)),
pointer_down_context_(false),
last_touch_location_(-1, -1),
@@ -450,7 +448,7 @@ void RenderWidgetHostViewWin::InitAsFullscreen(
gfx::Rect pos = gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
reference_host_view->GetNativeView()).bounds();
is_fullscreen_ = true;
- DoPopupOrFullscreenInit(ui::GetWindowToParentTo(true), pos, 0);
+ DoPopupOrFullscreenInit(gfx::GetWindowToParentTo(true), pos, 0);
}
RenderWidgetHost* RenderWidgetHostViewWin::GetRenderWidgetHost() const {
@@ -501,7 +499,7 @@ void RenderWidgetHostViewWin::SetSize(const gfx::Size& size) {
}
void RenderWidgetHostViewWin::SetBounds(const gfx::Rect& rect) {
- if (is_hidden_)
+ if (being_destroyed_)
return;
// No SWP_NOREDRAW as autofill popups can move and the underneath window
@@ -574,7 +572,7 @@ void RenderWidgetHostViewWin::CleanupCompositorWindow() {
if (!compositor_host_window_)
return;
- ui::SetWindowUserData(compositor_host_window_, NULL);
+ gfx::SetWindowUserData(compositor_host_window_, NULL);
// Hide the compositor and parent it to the desktop rather than destroying
// it immediately. The GPU process has a grace period to stop accessing the
@@ -625,7 +623,7 @@ void RenderWidgetHostViewWin::Show() {
}
void RenderWidgetHostViewWin::Hide() {
- if (!is_fullscreen_ && GetParent() == ui::GetWindowToParentTo(true)) {
+ if (!is_fullscreen_ && GetParent() == gfx::GetWindowToParentTo(true)) {
LOG(WARNING) << "Hide() called twice in a row: " << this << ":"
<< GetParent();
return;
@@ -643,7 +641,7 @@ bool RenderWidgetHostViewWin::IsShowing() {
}
gfx::Rect RenderWidgetHostViewWin::GetViewBounds() const {
- return ui::win::ScreenToDIPRect(GetPixelBounds());
+ return gfx::win::ScreenToDIPRect(GetPixelBounds());
}
gfx::Rect RenderWidgetHostViewWin::GetPixelBounds() const {
@@ -690,8 +688,8 @@ void RenderWidgetHostViewWin::SetIsLoading(bool is_loading) {
void RenderWidgetHostViewWin::TextInputTypeChanged(
ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) {
+ ui::TextInputMode input_mode,
+ bool can_compose_inline) {
if (text_input_type_ != type ||
text_input_mode_ != input_mode ||
can_compose_inline_ != can_compose_inline) {
@@ -725,7 +723,7 @@ void RenderWidgetHostViewWin::ImeCancelComposition() {
}
void RenderWidgetHostViewWin::ImeCompositionRangeChanged(
- const ui::Range& range,
+ const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) {
composition_range_ = range;
composition_character_bounds_ = character_bounds;
@@ -762,6 +760,7 @@ void RenderWidgetHostViewWin::DidUpdateBackingStore(
const gfx::Vector2d& scroll_delta,
const std::vector<gfx::Rect>& copy_rects,
const ui::LatencyInfo& latency_info) {
+ TRACE_EVENT0("content", "RenderWidgetHostViewWin::DidUpdateBackingStore");
software_latency_info_.MergeWith(latency_info);
if (is_hidden_)
return;
@@ -772,7 +771,7 @@ void RenderWidgetHostViewWin::DidUpdateBackingStore(
// surprisingly, this ordering matters.
for (size_t i = 0; i < copy_rects.size(); ++i) {
- gfx::Rect pixel_rect = ui::win::DIPToScreenRect(copy_rects[i]);
+ gfx::Rect pixel_rect = gfx::win::DIPToScreenRect(copy_rects[i]);
// Damage might not be DIP aligned.
pixel_rect.Inset(-1, -1);
RECT bounds = pixel_rect.ToRECT();
@@ -780,11 +779,12 @@ void RenderWidgetHostViewWin::DidUpdateBackingStore(
}
if (!scroll_rect.IsEmpty()) {
- gfx::Rect pixel_rect = ui::win::DIPToScreenRect(scroll_rect);
+ TRACE_EVENT0("content", "ScrollWindowEx");
+ gfx::Rect pixel_rect = gfx::win::DIPToScreenRect(scroll_rect);
// Damage might not be DIP aligned.
pixel_rect.Inset(-1, -1);
RECT clip_rect = pixel_rect.ToRECT();
- float scale = ui::win::GetDeviceScaleFactor();
+ float scale = gfx::win::GetDeviceScaleFactor();
int dx = static_cast<int>(scale * scroll_delta.x());
int dy = static_cast<int>(scale * scroll_delta.y());
ScrollWindowEx(dx, dy, NULL, &clip_rect, NULL, NULL, SW_INVALIDATE);
@@ -806,7 +806,7 @@ bool RenderWidgetHostViewWin::CanSubscribeFrame() const {
void RenderWidgetHostViewWin::WillWmDestroy() {
CleanupCompositorWindow();
- if (base::win::IsTSFAwareRequired() && GetFocus() == m_hWnd)
+ if (base::win::IsTSFAwareRequired())
ui::TSFBridge::GetInstance()->RemoveFocusedClient(this);
}
@@ -843,7 +843,7 @@ void RenderWidgetHostViewWin::SetTooltipText(const string16& tooltip_text) {
// accidentally DOS the user with a mega tooltip (since Windows doesn't seem
// to do this itself).
const string16 new_tooltip_text =
- ui::TruncateString(tooltip_text, kMaxTooltipLength);
+ gfx::TruncateString(tooltip_text, kMaxTooltipLength);
if (new_tooltip_text != tooltip_text_) {
tooltip_text_ = new_tooltip_text;
@@ -883,7 +883,7 @@ void RenderWidgetHostViewWin::CopyFromCompositingSurface(
if (dst_size.IsEmpty() || src_subrect.IsEmpty())
return;
- scoped_callback_runner.Release();
+ ignore_result(scoped_callback_runner.Release());
accelerated_surface_->AsyncCopyTo(src_subrect, dst_size, callback);
}
@@ -902,7 +902,7 @@ void RenderWidgetHostViewWin::CopyFromCompositingSurfaceToVideoFrame(
if (src_subrect.IsEmpty())
return;
- scoped_callback_runner.Release();
+ ignore_result(scoped_callback_runner.Release());
accelerated_surface_->AsyncCopyToVideoFrame(src_subrect, target, callback);
}
@@ -1018,7 +1018,7 @@ void RenderWidgetHostViewWin::InsertText(const string16& text) {
}
if (render_widget_host_)
render_widget_host_->ImeConfirmComposition(text,
- ui::Range::InvalidRange(),
+ gfx::Range::InvalidRange(),
false);
}
@@ -1048,7 +1048,7 @@ ui::TextInputMode RenderWidgetHostViewWin::GetTextInputMode() const {
NOTREACHED();
return ui::TEXT_INPUT_MODE_DEFAULT;
}
- return ui::TEXT_INPUT_MODE_DEFAULT;
+ return text_input_mode_;
}
bool RenderWidgetHostViewWin::CanComposeInline() const {
@@ -1096,7 +1096,7 @@ bool RenderWidgetHostViewWin::HasCompositionText() {
return false;
}
-bool RenderWidgetHostViewWin::GetTextRange(ui::Range* range) {
+bool RenderWidgetHostViewWin::GetTextRange(gfx::Range* range) {
if (!base::win::IsTSFAwareRequired()) {
NOTREACHED();
return false;
@@ -1106,7 +1106,7 @@ bool RenderWidgetHostViewWin::GetTextRange(ui::Range* range) {
return false;
}
-bool RenderWidgetHostViewWin::GetCompositionTextRange(ui::Range* range) {
+bool RenderWidgetHostViewWin::GetCompositionTextRange(gfx::Range* range) {
if (!base::win::IsTSFAwareRequired()) {
NOTREACHED();
return false;
@@ -1116,7 +1116,7 @@ bool RenderWidgetHostViewWin::GetCompositionTextRange(ui::Range* range) {
return false;
}
-bool RenderWidgetHostViewWin::GetSelectionRange(ui::Range* range) {
+bool RenderWidgetHostViewWin::GetSelectionRange(gfx::Range* range) {
if (!base::win::IsTSFAwareRequired()) {
NOTREACHED();
return false;
@@ -1126,7 +1126,7 @@ bool RenderWidgetHostViewWin::GetSelectionRange(ui::Range* range) {
return false;
}
-bool RenderWidgetHostViewWin::SetSelectionRange(const ui::Range& range) {
+bool RenderWidgetHostViewWin::SetSelectionRange(const gfx::Range& range) {
if (!base::win::IsTSFAwareRequired()) {
NOTREACHED();
return false;
@@ -1136,7 +1136,7 @@ bool RenderWidgetHostViewWin::SetSelectionRange(const ui::Range& range) {
return false;
}
-bool RenderWidgetHostViewWin::DeleteRange(const ui::Range& range) {
+bool RenderWidgetHostViewWin::DeleteRange(const gfx::Range& range) {
if (!base::win::IsTSFAwareRequired()) {
NOTREACHED();
return false;
@@ -1146,13 +1146,13 @@ bool RenderWidgetHostViewWin::DeleteRange(const ui::Range& range) {
return false;
}
-bool RenderWidgetHostViewWin::GetTextFromRange(const ui::Range& range,
+bool RenderWidgetHostViewWin::GetTextFromRange(const gfx::Range& range,
string16* text) {
if (!base::win::IsTSFAwareRequired()) {
NOTREACHED();
return false;
}
- ui::Range selection_text_range(selection_text_offset_,
+ gfx::Range selection_text_range(selection_text_offset_,
selection_text_offset_ + selection_text_.length());
if (!selection_text_range.Contains(range)) {
text->clear();
@@ -1313,7 +1313,7 @@ void RenderWidgetHostViewWin::OnPaint(HDC unused_dc) {
if (backing_store) {
gfx::Rect bitmap_rect(gfx::Point(),
- ui::win::DIPToScreenSize(backing_store->size()));
+ gfx::win::DIPToScreenSize(backing_store->size()));
bool manage_colors = BackingStoreWin::ColorManagementEnabled();
if (manage_colors)
@@ -1667,7 +1667,7 @@ LRESULT RenderWidgetHostViewWin::OnImeComposition(
ui::CompositionText composition;
if (imm32_manager_->GetResult(m_hWnd, lparam, &composition.text)) {
render_widget_host_->ImeConfirmComposition(
- composition.text, ui::Range::InvalidRange(), false);
+ composition.text, gfx::Range::InvalidRange(), false);
imm32_manager_->ResetComposition(m_hWnd);
// Fall though and try reading the composition string.
// Japanese IMEs send a message containing both GCS_RESULTSTR and
@@ -1679,7 +1679,7 @@ LRESULT RenderWidgetHostViewWin::OnImeComposition(
if (imm32_manager_->GetComposition(m_hWnd, lparam, &composition)) {
// TODO(suzhe): due to a bug of webkit, we can't use selection range with
// composition string. See: https://bugs.webkit.org/show_bug.cgi?id=37788
- composition.selection = ui::Range(composition.selection.end());
+ composition.selection = gfx::Range(composition.selection.end());
// TODO(suzhe): convert both renderer_host and renderer to use
// ui::CompositionText.
@@ -2001,7 +2001,7 @@ LRESULT RenderWidgetHostViewWin::OnWheelEvent(UINT message, WPARAM wparam,
if (render_widget_host_) {
WebKit::WebMouseWheelEvent wheel_event =
WebMouseWheelEventBuilder::Build(m_hWnd, message, wparam, lparam);
- float scale = ui::win::GetDeviceScaleFactor();
+ float scale = gfx::win::GetDeviceScaleFactor();
wheel_event.x /= scale;
wheel_event.y /= scale;
wheel_event.deltaX /= scale;
@@ -2014,7 +2014,9 @@ LRESULT RenderWidgetHostViewWin::OnWheelEvent(UINT message, WPARAM wparam,
}
WebTouchState::WebTouchState(const RenderWidgetHostViewWin* window)
- : window_(window) { }
+ : window_(window),
+ id_generator_(0) {
+}
size_t WebTouchState::UpdateTouchPoints(
TOUCHINPUT* points, size_t count) {
@@ -2114,22 +2116,12 @@ size_t WebTouchState::UpdateTouchPoints(
}
void WebTouchState::RemoveExpiredMappings() {
- WebTouchState::MapType new_map;
- for (MapType::iterator it = touch_map_.begin();
- it != touch_map_.end();
- ++it) {
- WebKit::WebTouchPoint* point = touch_event_.touches;
- WebKit::WebTouchPoint* end = point + touch_event_.touchesLength;
- while (point < end) {
- if ((point->id == it->second) &&
- (point->state != WebKit::WebTouchPoint::StateReleased)) {
- new_map.insert(*it);
- break;
- }
- point++;
- }
+ WebKit::WebTouchPoint* point = touch_event_.touches;
+ WebKit::WebTouchPoint* end = point + touch_event_.touchesLength;
+ for (; point < end; ++point) {
+ if (point->state == WebKit::WebTouchPoint::StateReleased)
+ id_generator_.ReleaseGeneratedID(point->id);
}
- touch_map_.swap(new_map);
}
@@ -2167,18 +2159,20 @@ bool WebTouchState::UpdateTouchPoint(
WebKit::WebTouchPoint* touch_point,
TOUCHINPUT* touch_input) {
CPoint coordinates(
- TOUCH_COORD_TO_PIXEL(touch_input->x) / ui::win::GetUndocumentedDPIScale(),
- TOUCH_COORD_TO_PIXEL(touch_input->y) / ui::win::GetUndocumentedDPIScale());
+ TOUCH_COORD_TO_PIXEL(touch_input->x) /
+ gfx::win::GetUndocumentedDPITouchScale(),
+ TOUCH_COORD_TO_PIXEL(touch_input->y) /
+ gfx::win::GetUndocumentedDPITouchScale());
int radius_x = 1;
int radius_y = 1;
if (touch_input->dwMask & TOUCHINPUTMASKF_CONTACTAREA) {
// Some touch drivers send a contact area of "-1", yet flag it as valid.
radius_x = std::max(1,
static_cast<int>(TOUCH_COORD_TO_PIXEL(touch_input->cxContact) /
- ui::win::GetUndocumentedDPIScale()));
+ gfx::win::GetUndocumentedDPITouchScale()));
radius_y = std::max(1,
static_cast<int>(TOUCH_COORD_TO_PIXEL(touch_input->cyContact) /
- ui::win::GetUndocumentedDPIScale()));
+ gfx::win::GetUndocumentedDPITouchScale()));
}
// Detect and exclude stationary moves.
@@ -2194,7 +2188,7 @@ bool WebTouchState::UpdateTouchPoint(
touch_point->screenPosition.x = coordinates.x;
touch_point->screenPosition.y = coordinates.y;
window_->ScreenToClient(&coordinates);
- static float scale = ui::win::GetDeviceScaleFactor();
+ static float scale = gfx::win::GetDeviceScaleFactor();
touch_point->position.x = coordinates.x / scale;
touch_point->position.y = coordinates.y / scale;
touch_point->radiusX = radius_x;
@@ -2206,14 +2200,7 @@ bool WebTouchState::UpdateTouchPoint(
// Find (or create) a mapping for _os_touch_id_.
unsigned int WebTouchState::GetMappedTouch(unsigned int os_touch_id) {
- MapType::iterator it = touch_map_.find(os_touch_id);
- if (it != touch_map_.end())
- return it->second;
- int next_value = 0;
- for (it = touch_map_.begin(); it != touch_map_.end(); ++it)
- next_value = std::max(next_value, it->second + 1);
- touch_map_[os_touch_id] = next_value;
- return next_value;
+ return id_generator_.GetGeneratedID(os_touch_id);
}
LRESULT RenderWidgetHostViewWin::OnTouchEvent(UINT message, WPARAM wparam,
@@ -2241,8 +2228,10 @@ LRESULT RenderWidgetHostViewWin::OnTouchEvent(UINT message, WPARAM wparam,
if (total == 1 && (points[0].dwFlags & TOUCHEVENTF_DOWN)) {
pointer_down_context_ = true;
last_touch_location_ = gfx::Point(
- TOUCH_COORD_TO_PIXEL(points[0].x) / ui::win::GetUndocumentedDPIScale(),
- TOUCH_COORD_TO_PIXEL(points[0].y) / ui::win::GetUndocumentedDPIScale());
+ TOUCH_COORD_TO_PIXEL(points[0].x) /
+ gfx::win::GetUndocumentedDPITouchScale(),
+ TOUCH_COORD_TO_PIXEL(points[0].y) /
+ gfx::win::GetUndocumentedDPITouchScale());
}
bool should_forward = render_widget_host_->ShouldForwardTouchEvent() &&
@@ -2311,7 +2300,7 @@ LRESULT RenderWidgetHostViewWin::OnMouseActivate(UINT message,
::ScreenToClient(m_hWnd, &cursor_pos);
HWND child_window = ::RealChildWindowFromPoint(m_hWnd, cursor_pos);
if (::IsWindow(child_window) && child_window != m_hWnd) {
- if (ui::GetClassName(child_window) == kWrapperNativeWindowClassName)
+ if (gfx::GetClassName(child_window) == kWrapperNativeWindowClassName)
child_window = ::GetWindow(child_window, GW_CHILD);
::SetFocus(child_window);
@@ -2372,10 +2361,10 @@ LRESULT RenderWidgetHostViewWin::OnMoveOrSize(
return 0;
}
-void RenderWidgetHostViewWin::OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>& params) {
+void RenderWidgetHostViewWin::OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>& params) {
CreateBrowserAccessibilityManagerIfNeeded();
- GetBrowserAccessibilityManager()->OnAccessibilityNotifications(params);
+ GetBrowserAccessibilityManager()->OnAccessibilityEvents(params);
}
bool RenderWidgetHostViewWin::LockMouse() {
@@ -2457,7 +2446,7 @@ static void PaintCompositorHostWindow(HWND hWnd) {
BeginPaint(hWnd, &paint);
RenderWidgetHostViewWin* win = static_cast<RenderWidgetHostViewWin*>(
- ui::GetWindowUserData(hWnd));
+ gfx::GetWindowUserData(hWnd));
// Trigger composite to rerender window.
if (win)
win->AcceleratedPaint(paint.hdc);
@@ -2506,7 +2495,7 @@ gfx::Rect RenderWidgetHostViewWin::GetBoundsInRootWindow() {
GetSystemMetrics(SM_CYSIZEFRAME));
}
- return ui::win::ScreenToDIPRect(rect);
+ return gfx::win::ScreenToDIPRect(rect);
}
// Creates a HWND within the RenderWidgetHostView that will serve as a host
@@ -2556,9 +2545,9 @@ gfx::GLSurfaceHandle RenderWidgetHostViewWin::GetCompositingSurface() {
MAKEINTATOM(atom), 0,
WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_DISABLED,
0, 0, width, height, m_hWnd, 0, instance, 0);
- ui::CheckWindowCreated(compositor_host_window_);
+ gfx::CheckWindowCreated(compositor_host_window_);
- ui::SetWindowUserData(compositor_host_window_, this);
+ gfx::SetWindowUserData(compositor_host_window_, this);
gfx::GLSurfaceHandle surface_handle(compositor_host_window_,
gfx::NATIVE_TRANSPORT);
@@ -2754,6 +2743,8 @@ void RenderWidgetHostViewWin::OnFinalMessage(HWND window) {
}
if (render_widget_host_)
render_widget_host_->ViewDestroyed();
+ if (base::win::IsTSFAwareRequired())
+ ui::TSFBridge::GetInstance()->RemoveFocusedClient(this);
delete this;
}
@@ -2887,7 +2878,7 @@ void RenderWidgetHostViewWin::ForwardMouseEventToRenderer(UINT message,
return;
}
- gfx::Point point = ui::win::ScreenToDIPPoint(
+ gfx::Point point = gfx::win::ScreenToDIPPoint(
gfx::Point(static_cast<short>(LOWORD(lparam)),
static_cast<short>(HIWORD(lparam))));
lparam = MAKELPARAM(point.x(), point.y());
@@ -2966,7 +2957,7 @@ void RenderWidgetHostViewWin::DoPopupOrFullscreenInit(HWND parent_hwnd,
const gfx::Rect& pos,
DWORD ex_style) {
Create(parent_hwnd, NULL, NULL, WS_POPUP, ex_style);
- gfx::Rect screen_rect = ui::win::DIPToScreenRect(pos);
+ gfx::Rect screen_rect = gfx::win::DIPToScreenRect(pos);
MoveWindow(screen_rect.x(), screen_rect.y(), screen_rect.width(),
screen_rect.height(), TRUE);
ShowWindow(IsActivatable() ? SW_SHOW : SW_SHOWNA);
@@ -3180,7 +3171,7 @@ void RenderWidgetHostViewWin::UpdateInputScopeIfNecessary(
return;
ui::tsf_inputscope::SetInputScopeForTsfUnawareWindow(
- m_hWnd, text_input_type, ui::TEXT_INPUT_MODE_DEFAULT);
+ m_hWnd, text_input_type, text_input_mode_);
}
////////////////////////////////////////////////////////////////////////////////
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 52030d78f39..6650ae4ba8b 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
@@ -182,14 +182,14 @@ class RenderWidgetHostViewWin
virtual void UpdateCursor(const WebCursor& cursor) OVERRIDE;
virtual void SetIsLoading(bool is_loading) OVERRIDE;
virtual void TextInputTypeChanged(ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) OVERRIDE;
+ ui::TextInputMode input_mode,
+ bool can_compose_inline) OVERRIDE;
virtual void SelectionBoundsChanged(
const ViewHostMsg_SelectionBounds_Params& params) OVERRIDE;
virtual void ScrollOffsetChanged() OVERRIDE;
virtual void ImeCancelComposition() OVERRIDE;
virtual void ImeCompositionRangeChanged(
- const ui::Range& range,
+ const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) OVERRIDE;
virtual void DidUpdateBackingStore(
const gfx::Rect& scroll_rect,
@@ -233,8 +233,8 @@ class RenderWidgetHostViewWin
virtual void AcceleratedSurfaceSuspend() OVERRIDE;
virtual void AcceleratedSurfaceRelease() OVERRIDE;
virtual bool HasAcceleratedSurface(const gfx::Size& desired_size) OVERRIDE;
- virtual void OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>& params
+ virtual void OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>& params
) OVERRIDE;
virtual bool LockMouse() OVERRIDE;
virtual void UnlockMouse() OVERRIDE;
@@ -277,12 +277,12 @@ class RenderWidgetHostViewWin
virtual bool GetCompositionCharacterBounds(uint32 index,
gfx::Rect* rect) OVERRIDE;
virtual bool HasCompositionText() OVERRIDE;
- virtual bool GetTextRange(ui::Range* range) OVERRIDE;
- virtual bool GetCompositionTextRange(ui::Range* range) OVERRIDE;
- virtual bool GetSelectionRange(ui::Range* range) OVERRIDE;
- virtual bool SetSelectionRange(const ui::Range& range) OVERRIDE;
- virtual bool DeleteRange(const ui::Range& range) OVERRIDE;
- virtual bool GetTextFromRange(const ui::Range& range,
+ virtual bool GetTextRange(gfx::Range* range) OVERRIDE;
+ virtual bool GetCompositionTextRange(gfx::Range* range) OVERRIDE;
+ virtual bool GetSelectionRange(gfx::Range* range) 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;
virtual void OnInputMethodChanged() OVERRIDE;
virtual bool ChangeTextDirectionAndLayoutAlignment(
@@ -572,7 +572,7 @@ class RenderWidgetHostViewWin
// back, we regard the mouse movement as (0, 0).
bool ignore_mouse_movement_;
- ui::Range composition_range_;
+ gfx::Range composition_range_;
// The current composition character bounds.
std::vector<gfx::Rect> composition_character_bounds_;
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
index 76070bc70e5..fc73601fb6c 100644
--- 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
@@ -10,11 +10,11 @@
#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/test_utils.h"
#include "content/public/test/browser_test_utils.h"
-#include "content/shell/shell.h"
-#include "content/test/content_browser_test_utils.h"
+#include "content/public/test/test_utils.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.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"
@@ -87,16 +87,16 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewWinBrowserTest,
MockIMM32Manager* mock = new MockIMM32Manager();
mock->Reset();
view_->imm32_manager_.reset(mock);
- view_->TextInputTypeChanged(ui::TEXT_INPUT_TYPE_NONE, false,
- ui::TEXT_INPUT_MODE_EMAIL);
+ 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, false,
- ui::TEXT_INPUT_MODE_EMAIL);
+ view_->TextInputTypeChanged(ui::TEXT_INPUT_TYPE_NONE,
+ ui::TEXT_INPUT_MODE_EMAIL, false);
EXPECT_EQ(0, mock->call_count());
}
diff --git a/chromium/content/browser/renderer_host/smooth_scroll_calculator.cc b/chromium/content/browser/renderer_host/smooth_scroll_calculator.cc
deleted file mode 100644
index 2538a188354..00000000000
--- a/chromium/content/browser/renderer_host/smooth_scroll_calculator.cc
+++ /dev/null
@@ -1,28 +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/smooth_scroll_calculator.h"
-
-namespace content {
-
-SmoothScrollCalculator::SmoothScrollCalculator() {
-}
-
-SmoothScrollCalculator::~SmoothScrollCalculator() {
-}
-
-double SmoothScrollCalculator::GetScrollDelta(
- base::TimeTicks now, base::TimeDelta desired_interval) {
- double position_delta = 10;
- if (!last_tick_time_.is_null()) {
- double velocity = 10 / desired_interval.InMillisecondsF();
- double 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/smooth_scroll_calculator.h b/chromium/content/browser/renderer_host/smooth_scroll_calculator.h
deleted file mode 100644
index 1427416be41..00000000000
--- a/chromium/content/browser/renderer_host/smooth_scroll_calculator.h
+++ /dev/null
@@ -1,29 +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_SMOOTH_SCROLL_CALCULATOR_H_
-#define CONTENT_BROWSER_RENDERER_HOST_SMOOTH_SCROLL_CALCULATOR_H_
-
-#include "base/time/time.h"
-
-namespace content {
-
-// An utility class to calculate the delta for smooth scroll gesture
-// events.
-class SmoothScrollCalculator {
- public:
- SmoothScrollCalculator();
- ~SmoothScrollCalculator();
-
- double GetScrollDelta(base::TimeTicks now, base::TimeDelta desired_interval);
-
- private:
- base::TimeTicks last_tick_time_;
-
- DISALLOW_COPY_AND_ASSIGN(SmoothScrollCalculator);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_SMOOTH_SCROLL_CALCULATOR_H_
diff --git a/chromium/content/browser/renderer_host/smooth_scroll_gesture_controller.cc b/chromium/content/browser/renderer_host/smooth_scroll_gesture_controller.cc
deleted file mode 100644
index ca9dfae9b78..00000000000
--- a/chromium/content/browser/renderer_host/smooth_scroll_gesture_controller.cc
+++ /dev/null
@@ -1,61 +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/smooth_scroll_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/smooth_scroll_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 kSyntheticScrollMessageIntervalMs = 7;
-
-} // namespace
-
-SmoothScrollGestureController::SmoothScrollGestureController()
- : rwh_(NULL) {
-}
-
-SmoothScrollGestureController::~SmoothScrollGestureController() {
-}
-
-void SmoothScrollGestureController::BeginSmoothScroll(
- RenderWidgetHostViewPort* view,
- const ViewHostMsg_BeginSmoothScroll_Params& params) {
- if (pending_smooth_scroll_gesture_.get())
- return;
-
- rwh_ = view->GetRenderWidgetHost();
- pending_smooth_scroll_gesture_ = view->CreateSmoothScrollGesture(
- params.scroll_down,
- params.pixels_to_scroll,
- params.mouse_event_x,
- params.mouse_event_y);
-
- timer_.Start(FROM_HERE, GetSyntheticScrollMessageInterval(), this,
- &SmoothScrollGestureController::OnTimer);
-}
-
-base::TimeDelta
- SmoothScrollGestureController::GetSyntheticScrollMessageInterval() const {
- return base::TimeDelta::FromMilliseconds(kSyntheticScrollMessageIntervalMs);
-}
-
-void SmoothScrollGestureController::OnTimer() {
- base::TimeTicks now = base::TimeTicks::Now();
- if (!pending_smooth_scroll_gesture_->ForwardInputEvents(now, rwh_)) {
- timer_.Stop();
- pending_smooth_scroll_gesture_ = NULL;
- rwh_->Send(new ViewMsg_SmoothScrollCompleted(rwh_->GetRoutingID()));
- }
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/smooth_scroll_gesture_controller.h b/chromium/content/browser/renderer_host/smooth_scroll_gesture_controller.h
deleted file mode 100644
index 1477a171e6a..00000000000
--- a/chromium/content/browser/renderer_host/smooth_scroll_gesture_controller.h
+++ /dev/null
@@ -1,52 +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_SMOOTH_SCROLL_GESTURE_CONTROLLER_H_
-#define CONTENT_BROWSER_RENDERER_HOST_SMOOTH_SCROLL_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_BeginSmoothScroll_Params;
-
-namespace content {
-
-class RenderWidgetHost;
-class RenderWidgetHostViewPort;
-class SmoothScrollGesture;
-
-// Controls SmoothScrollGestures, used to inject synthetic events
-// for performance test harness.
-class CONTENT_EXPORT SmoothScrollGestureController {
- public:
- SmoothScrollGestureController();
- ~SmoothScrollGestureController();
-
- // Initiates a synthetic event stream.
- void BeginSmoothScroll(RenderWidgetHostViewPort* view,
- const ViewHostMsg_BeginSmoothScroll_Params& params);
-
- base::TimeDelta GetSyntheticScrollMessageInterval() const;
-
- private:
- // Called periodically to advance the active scroll gesture after being
- // initiated by OnBeginSmoothScroll.
- void OnTimer();
-
- base::RepeatingTimer<SmoothScrollGestureController> timer_;
-
- RenderWidgetHost* rwh_;
-
- scoped_refptr<SmoothScrollGesture> pending_smooth_scroll_gesture_;
-
- DISALLOW_COPY_AND_ASSIGN(SmoothScrollGestureController);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_SMOOTH_SCROLL_GESTURE_CONTROLLER_H_
diff --git a/chromium/content/browser/renderer_host/socket_stream_dispatcher_host.cc b/chromium/content/browser/renderer_host/socket_stream_dispatcher_host.cc
index 7f122df2c73..677c281932c 100644
--- a/chromium/content/browser/renderer_host/socket_stream_dispatcher_host.cc
+++ b/chromium/content/browser/renderer_host/socket_stream_dispatcher_host.cc
@@ -30,14 +30,13 @@ const size_t kMaxSocketStreamHosts = 16 * 1024;
SocketStreamDispatcherHost::SocketStreamDispatcherHost(
int render_process_id,
- ResourceMessageFilter::URLRequestContextSelector* selector,
+ const GetRequestContextCallback& request_context_callback,
ResourceContext* resource_context)
: render_process_id_(render_process_id),
- url_request_context_selector_(selector),
+ request_context_callback_(request_context_callback),
resource_context_(resource_context),
weak_ptr_factory_(this),
on_shutdown_(false) {
- DCHECK(selector);
net::WebSocketJob::EnsureInit();
}
@@ -263,8 +262,7 @@ void SocketStreamDispatcherHost::DeleteSocketStreamHost(int socket_id) {
}
net::URLRequestContext* SocketStreamDispatcherHost::GetURLRequestContext() {
- return url_request_context_selector_->GetRequestContext(
- ResourceType::SUB_RESOURCE);
+ return request_context_callback_.Run(ResourceType::SUB_RESOURCE);
}
void SocketStreamDispatcherHost::Shutdown() {
diff --git a/chromium/content/browser/renderer_host/socket_stream_dispatcher_host.h b/chromium/content/browser/renderer_host/socket_stream_dispatcher_host.h
index 732923e690f..958eada3a57 100644
--- a/chromium/content/browser/renderer_host/socket_stream_dispatcher_host.h
+++ b/chromium/content/browser/renderer_host/socket_stream_dispatcher_host.h
@@ -7,9 +7,9 @@
#include <vector>
+#include "base/callback_forward.h"
#include "base/id_map.h"
#include "base/memory/weak_ptr.h"
-#include "content/browser/loader/resource_message_filter.h"
#include "content/browser/ssl/ssl_error_handler.h"
#include "content/public/browser/browser_message_filter.h"
#include "net/socket_stream/socket_stream.h"
@@ -32,9 +32,11 @@ class SocketStreamDispatcherHost
public net::SocketStream::Delegate,
public SSLErrorHandler::Delegate {
public:
+ typedef base::Callback<net::URLRequestContext*(ResourceType::Type)>
+ GetRequestContextCallback;
SocketStreamDispatcherHost(
int render_process_id,
- ResourceMessageFilter::URLRequestContextSelector* selector,
+ const GetRequestContextCallback& request_context_callback,
ResourceContext* resource_context);
// BrowserMessageFilter:
@@ -84,8 +86,7 @@ class SocketStreamDispatcherHost
IDMap<SocketStreamHost> hosts_;
int render_process_id_;
- const scoped_ptr<ResourceMessageFilter::URLRequestContextSelector>
- url_request_context_selector_;
+ GetRequestContextCallback request_context_callback_;
ResourceContext* resource_context_;
base::WeakPtrFactory<SocketStreamDispatcherHost> weak_ptr_factory_;
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
index b563480efd9..d382cd57565 100644
--- a/chromium/content/browser/renderer_host/surface_texture_transport_client_android.cc
+++ b/chromium/content/browser/renderer_host/surface_texture_transport_client_android.cc
@@ -15,7 +15,7 @@
#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_bridge.h"
+#include "ui/gl/android/surface_texture.h"
namespace content {
@@ -26,7 +26,7 @@ static const uint32 kGLTextureExternalOES = 0x8D65;
class SurfaceRefAndroid : public GpuSurfaceTracker::SurfaceRef {
public:
SurfaceRefAndroid(
- const scoped_refptr<gfx::SurfaceTextureBridge>& surface,
+ const scoped_refptr<gfx::SurfaceTexture>& surface,
ANativeWindow* window)
: surface_(surface),
window_(window) {
@@ -39,7 +39,7 @@ class SurfaceRefAndroid : public GpuSurfaceTracker::SurfaceRef {
ANativeWindow_release(window_);
}
- scoped_refptr<gfx::SurfaceTextureBridge> surface_;
+ scoped_refptr<gfx::SurfaceTexture> surface_;
ANativeWindow* window_;
};
@@ -61,7 +61,7 @@ scoped_refptr<cc::Layer> SurfaceTextureTransportClient::Initialize() {
// Use a SurfaceTexture to stream frames to the UI thread.
video_layer_ = cc::VideoLayer::Create(this);
- surface_texture_ = new gfx::SurfaceTextureBridge(0);
+ surface_texture_ = new gfx::SurfaceTexture(0);
surface_texture_->SetFrameAvailableCallback(
base::Bind(
&SurfaceTextureTransportClient::OnSurfaceTextureFrameAvailable,
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
index 83d917552dc..5a000bb246e 100644
--- a/chromium/content/browser/renderer_host/surface_texture_transport_client_android.h
+++ b/chromium/content/browser/renderer_host/surface_texture_transport_client_android.h
@@ -21,7 +21,7 @@ class VideoLayer;
}
namespace gfx {
-class SurfaceTextureBridge;
+class SurfaceTexture;
}
namespace content {
@@ -45,7 +45,7 @@ class SurfaceTextureTransportClient : public cc::VideoFrameProvider {
void OnSurfaceTextureFrameAvailable();
scoped_refptr<cc::VideoLayer> video_layer_;
- scoped_refptr<gfx::SurfaceTextureBridge> surface_texture_;
+ scoped_refptr<gfx::SurfaceTexture> surface_texture_;
ANativeWindow* window_;
scoped_refptr<media::VideoFrame> video_frame_;
uint32 texture_id_;
diff --git a/chromium/content/browser/renderer_host/synthetic_gesture_calculator.cc b/chromium/content/browser/renderer_host/synthetic_gesture_calculator.cc
new file mode 100644
index 00000000000..9816df93b48
--- /dev/null
+++ b/chromium/content/browser/renderer_host/synthetic_gesture_calculator.cc
@@ -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.
+
+#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
new file mode 100644
index 00000000000..c2af4978ac4
--- /dev/null
+++ b/chromium/content/browser/renderer_host/synthetic_gesture_calculator.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_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
new file mode 100644
index 00000000000..46c4329da6b
--- /dev/null
+++ b/chromium/content/browser/renderer_host/synthetic_gesture_controller.cc
@@ -0,0 +1,84 @@
+// Copyright 2013 The Chromium Authors. All rights 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
new file mode 100644
index 00000000000..8826aaddf3a
--- /dev/null
+++ b/chromium/content/browser/renderer_host/synthetic_gesture_controller.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_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/smooth_scroll_gesture_controller_unittest.cc b/chromium/content/browser/renderer_host/synthetic_gesture_controller_unittest.cc
index 95d26473ee1..7fb9ba9e601 100644
--- a/chromium/content/browser/renderer_host/smooth_scroll_gesture_controller_unittest.cc
+++ b/chromium/content/browser/renderer_host/synthetic_gesture_controller_unittest.cc
@@ -1,4 +1,4 @@
-// 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.
@@ -6,11 +6,11 @@
#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/smooth_scroll_gesture_controller.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/smooth_scroll_gesture.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"
@@ -26,9 +26,9 @@ namespace content {
namespace {
-class MockSmoothScrollGesture : public SmoothScrollGesture {
+class MockSyntheticGesture : public SyntheticGesture {
public:
- MockSmoothScrollGesture() :
+ MockSyntheticGesture() :
called_(0) {
}
@@ -42,7 +42,7 @@ class MockSmoothScrollGesture : public SmoothScrollGesture {
int called_;
protected:
- virtual ~MockSmoothScrollGesture() {
+ virtual ~MockSyntheticGesture() {
}
};
@@ -59,7 +59,7 @@ class MockRenderWidgetHost : public RenderWidgetHostImpl {
RenderWidgetHostDelegate* delegate,
RenderProcessHost* process,
int routing_id)
- : RenderWidgetHostImpl(delegate, process, routing_id) {
+ : RenderWidgetHostImpl(delegate, process, routing_id, false) {
}
virtual ~MockRenderWidgetHost() {}
};
@@ -73,10 +73,10 @@ class TestView : public TestRenderWidgetHostView {
virtual ~TestView() {}
// TestRenderWidgetHostView implementation:
- virtual SmoothScrollGesture* CreateSmoothScrollGesture(
+ virtual SyntheticGesture* CreateSmoothScrollGesture(
bool scroll_down, int pixels_to_scroll, int mouse_event_x,
int mouse_event_y) OVERRIDE {
- mock_gesture_ = new MockSmoothScrollGesture();
+ mock_gesture_ = new MockSyntheticGesture();
return mock_gesture_;
}
@@ -84,14 +84,14 @@ class TestView : public TestRenderWidgetHostView {
return rwh_;
}
- MockSmoothScrollGesture* mock_gesture_;
+ MockSyntheticGesture* mock_gesture_;
};
-class SmoothScrollGestureControllerTest : public testing::Test {
+class SyntheticGestureControllerTest : public testing::Test {
public:
- SmoothScrollGestureControllerTest() : process_(NULL) {
+ SyntheticGestureControllerTest() : process_(NULL) {
}
- virtual ~SmoothScrollGestureControllerTest() {}
+ virtual ~SyntheticGestureControllerTest() {}
protected:
// testing::Test implementation:
@@ -131,7 +131,7 @@ class SmoothScrollGestureControllerTest : public testing::Test {
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE, base::MessageLoop::QuitClosure(),
TimeDelta::FromMilliseconds(
- controller_.GetSyntheticScrollMessageInterval().InMilliseconds() *
+ controller_.GetSyntheticGestureMessageInterval().InMilliseconds() *
3));
base::MessageLoop::current()->Run();
}
@@ -147,10 +147,10 @@ class SmoothScrollGestureControllerTest : public testing::Test {
scoped_ptr<gfx::Screen> screen_;
#endif
- SmoothScrollGestureController controller_;
+ SyntheticGestureController controller_;
};
-TEST_F(SmoothScrollGestureControllerTest, Tick) {
+TEST_F(SyntheticGestureControllerTest, Tick) {
ViewHostMsg_BeginSmoothScroll_Params params;
params.scroll_down = true;
params.pixels_to_scroll = 10;
@@ -168,7 +168,7 @@ TEST_F(SmoothScrollGestureControllerTest, Tick) {
EXPECT_LT(0, current_ticks);
// Ensure it won't start another smooth scroll.
- MockSmoothScrollGesture* original_gesture = view_->mock_gesture_;
+ MockSyntheticGesture* original_gesture = view_->mock_gesture_;
controller_.BeginSmoothScroll(view_.get(), params);
PostQuitMessageAndRun();
EXPECT_EQ(original_gesture, view_->mock_gesture_);
diff --git a/chromium/content/browser/renderer_host/test_render_view_host.cc b/chromium/content/browser/renderer_host/test_render_view_host.cc
index 129591cac7b..caf79cf8583 100644
--- a/chromium/content/browser/renderer_host/test_render_view_host.cc
+++ b/chromium/content/browser/renderer_host/test_render_view_host.cc
@@ -15,7 +15,6 @@
#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_client.h"
#include "content/public/common/page_state.h"
-#include "content/public/common/password_form.h"
#include "content/test/test_web_contents.h"
#include "media/base/video_frame.h"
#include "ui/gfx/rect.h"
@@ -42,7 +41,6 @@ void InitNavigateParams(ViewHostMsg_FrameNavigate_Params* params,
params->should_update_history = false;
params->searchable_form_url = GURL();
params->searchable_form_encoding = std::string();
- params->password_form = PasswordForm();
params->security_info = std::string();
params->gesture = NavigationGestureUser;
params->was_within_same_page = false;
@@ -214,14 +212,6 @@ void TestRenderWidgetHostView::SetClickthroughRegion(SkRegion* region) {
}
#endif
-#if defined(OS_WIN) && defined(USE_AURA)
-gfx::NativeViewAccessible
-TestRenderWidgetHostView::AccessibleObjectFromChildId(long child_id) {
- NOTIMPLEMENTED();
- return NULL;
-}
-#endif
-
bool TestRenderWidgetHostView::LockMouse() {
return false;
}
@@ -247,7 +237,8 @@ TestRenderViewHost::TestRenderViewHost(
widget_delegate,
routing_id,
main_frame_routing_id,
- swapped_out),
+ swapped_out,
+ false /* hidden */),
render_view_created_(false),
delete_counter_(NULL),
simulate_fetch_via_proxy_(false),
@@ -333,7 +324,6 @@ void TestRenderViewHost::SendNavigateWithParameters(
params.should_update_history = true;
params.searchable_form_url = GURL();
params.searchable_form_encoding = std::string();
- params.password_form = PasswordForm();
params.security_info = std::string();
params.gesture = NavigationGestureUser;
params.contents_mime_type = contents_mime_type_;
diff --git a/chromium/content/browser/renderer_host/test_render_view_host.h b/chromium/content/browser/renderer_host/test_render_view_host.h
index 37b46e2bef8..1eb7583bec0 100644
--- a/chromium/content/browser/renderer_host/test_render_view_host.h
+++ b/chromium/content/browser/renderer_host/test_render_view_host.h
@@ -99,12 +99,12 @@ class TestRenderWidgetHostView : public RenderWidgetHostViewBase {
virtual void SetIsLoading(bool is_loading) OVERRIDE {}
virtual void UpdateCursor(const WebCursor& cursor) OVERRIDE {}
virtual void TextInputTypeChanged(ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) OVERRIDE {}
+ 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 ui::Range& range,
+ const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) OVERRIDE {}
#endif
virtual void DidUpdateBackingStore(
@@ -158,17 +158,12 @@ class TestRenderWidgetHostView : public RenderWidgetHostViewBase {
bool has_horizontal_scrollbar) OVERRIDE { }
virtual void SetScrollOffsetPinning(
bool is_pinned_to_left, bool is_pinned_to_right) OVERRIDE { }
- virtual void OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>&
- params) 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
-#if defined(OS_WIN) && defined(USE_AURA)
- virtual gfx::NativeViewAccessible AccessibleObjectFromChildId(long child_id)
- OVERRIDE;
-#endif
virtual bool LockMouse() OVERRIDE;
virtual void UnlockMouse() OVERRIDE;
#if defined(OS_WIN) && defined(USE_AURA)
diff --git a/chromium/content/browser/renderer_host/text_input_client_mac.mm b/chromium/content/browser/renderer_host/text_input_client_mac.mm
index cdf56a1eb19..b9d900a704e 100644
--- a/chromium/content/browser/renderer_host/text_input_client_mac.mm
+++ b/chromium/content/browser/renderer_host/text_input_client_mac.mm
@@ -61,7 +61,7 @@ NSRect TextInputClientMac::GetFirstRectForRange(RenderWidgetHost* rwh,
RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rwh);
rwhi->Send(
new TextInputClientMsg_FirstRectForCharacterRange(rwhi->GetRoutingID(),
- ui::Range(range)));
+ gfx::Range(range)));
// http://crbug.com/121917
base::ThreadRestrictions::ScopedAllowWait allow_wait;
condition_.TimedWait(base::TimeDelta::FromMilliseconds(kWaitTimeout));
@@ -82,7 +82,7 @@ NSAttributedString* TextInputClientMac::GetAttributedSubstringFromRange(
BeforeRequest();
RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rwh);
rwhi->Send(new TextInputClientMsg_StringForRange(rwhi->GetRoutingID(),
- ui::Range(range)));
+ gfx::Range(range)));
// http://crbug.com/121917
base::ThreadRestrictions::ScopedAllowWait allow_wait;
condition_.TimedWait(base::TimeDelta::FromMilliseconds(kWaitTimeout));
diff --git a/chromium/content/browser/renderer_host/text_input_client_mac_unittest.mm b/chromium/content/browser/renderer_host/text_input_client_mac_unittest.mm
index 2a4c6d7f08d..0993018e8f4 100644
--- a/chromium/content/browser/renderer_host/text_input_client_mac_unittest.mm
+++ b/chromium/content/browser/renderer_host/text_input_client_mac_unittest.mm
@@ -42,7 +42,7 @@ class TextInputClientMacTest : public testing::Test {
widget_(&delegate_,
process_factory_.CreateRenderProcessHost(
&browser_context_, NULL),
- MSG_ROUTING_NONE),
+ MSG_ROUTING_NONE, false),
thread_("TextInputClientMacTestThread") {}
// Accessor for the TextInputClientMac instance.
diff --git a/chromium/content/browser/renderer_host/text_input_client_message_filter.h b/chromium/content/browser/renderer_host/text_input_client_message_filter.h
index 2a374df5c5e..5a1405ae5ff 100644
--- a/chromium/content/browser/renderer_host/text_input_client_message_filter.h
+++ b/chromium/content/browser/renderer_host/text_input_client_message_filter.h
@@ -9,11 +9,8 @@
#include "content/public/browser/browser_message_filter.h"
namespace gfx {
-class Rect;
-}
-
-namespace ui {
class Range;
+class Rect;
}
namespace content {
diff --git a/chromium/content/browser/renderer_host/text_input_client_message_filter.mm b/chromium/content/browser/renderer_host/text_input_client_message_filter.mm
index cea0a347d70..7af5a8ff2bd 100644
--- a/chromium/content/browser/renderer_host/text_input_client_message_filter.mm
+++ b/chromium/content/browser/renderer_host/text_input_client_message_filter.mm
@@ -10,7 +10,7 @@
#include "content/common/text_input_client_messages.h"
#include "content/public/browser/render_widget_host_view.h"
#include "ipc/ipc_message_macros.h"
-#include "ui/base/range/range.h"
+#include "ui/gfx/range/range.h"
#include "ui/gfx/rect.h"
namespace content {
diff --git a/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_android.cc b/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_android.cc
deleted file mode 100644
index c504f6c07c9..00000000000
--- a/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_android.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_android.h"
-
-#include "base/debug/trace_event.h"
-#include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "jni/SmoothScroller_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 {
-
-TouchSmoothScrollGestureAndroid::TouchSmoothScrollGestureAndroid(
- int pixels_to_scroll,
- RenderWidgetHost* rwh,
- base::android::ScopedJavaLocalRef<jobject> java_scroller)
- : pixels_scrolled_(0),
- has_started_(false),
- has_sent_motion_up_(false),
- pixels_to_scroll_(pixels_to_scroll),
- rwh_(rwh),
- java_scroller_(java_scroller) {
- JNIEnv* env = base::android::AttachCurrentThread();
- RegisterNativesIfNeeded(env);
-}
-
-TouchSmoothScrollGestureAndroid::~TouchSmoothScrollGestureAndroid() {
-}
-
-bool TouchSmoothScrollGestureAndroid::ForwardInputEvents(
- base::TimeTicks now, RenderWidgetHost* host) {
- if (!has_started_) {
- has_started_ = true;
- JNIEnv* env = base::android::AttachCurrentThread();
- Java_SmoothScroller_start(
- env, java_scroller_.obj(), reinterpret_cast<int>(this));
- }
-
- TRACE_COUNTER_ID1(
- "gpu", "smooth_scroll_by_pixels_scrolled", this, pixels_scrolled_);
-
- return !has_sent_motion_up_;
-}
-
-double TouchSmoothScrollGestureAndroid::GetScrollDelta(
- JNIEnv* env, jobject obj, double scale) {
- double delta = smooth_scroll_calculator_.GetScrollDelta(
- base::TimeTicks::Now(),
- RenderWidgetHostImpl::From(rwh_)->GetSyntheticScrollMessageInterval())
- * scale;
- pixels_scrolled_ += delta;
- return delta;
-}
-
-bool TouchSmoothScrollGestureAndroid::HasFinished(JNIEnv* env, jobject obj) {
- return pixels_scrolled_ >= pixels_to_scroll_;
-}
-
-void TouchSmoothScrollGestureAndroid::SetHasSentMotionUp(
- JNIEnv* env, jobject obj) {
- has_sent_motion_up_ = true;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_android.h b/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_android.h
deleted file mode 100644
index 0b892670643..00000000000
--- a/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_android.h
+++ /dev/null
@@ -1,52 +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_GESTURE_ANDROID_H_
-#define CONTENT_BROWSER_RENDERER_HOST_TOUCH_SMOOTH_GESTURE_ANDROID_H_
-
-#include "base/android/jni_android.h"
-#include "base/time/time.h"
-#include "content/browser/renderer_host/smooth_scroll_calculator.h"
-#include "content/port/browser/smooth_scroll_gesture.h"
-
-namespace content {
-
-class ContentViewCore;
-class RenderWidgetHost;
-
-class TouchSmoothScrollGestureAndroid : public SmoothScrollGesture {
- public:
- TouchSmoothScrollGestureAndroid(
- int pixels_to_scroll,
- RenderWidgetHost* rwh,
- base::android::ScopedJavaLocalRef<jobject> java_scroller);
-
- // Called by the java side once the TimeAnimator ticks.
- double GetScrollDelta(JNIEnv* env, jobject obj, double scale);
- bool HasFinished(JNIEnv* env, jobject obj);
- void SetHasSentMotionUp(JNIEnv* env, jobject obj);
-
- // SmoothScrollGesture
- virtual bool ForwardInputEvents(base::TimeTicks now,
- RenderWidgetHost* host) OVERRIDE;
-
- private:
- virtual ~TouchSmoothScrollGestureAndroid();
-
- SmoothScrollCalculator smooth_scroll_calculator_;
-
- int pixels_scrolled_;
- bool has_started_;
- bool has_sent_motion_up_;
-
- int pixels_to_scroll_;
- RenderWidgetHost* rwh_;
- base::android::ScopedJavaGlobalRef<jobject> java_scroller_;
-
- DISALLOW_COPY_AND_ASSIGN(TouchSmoothScrollGestureAndroid);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_TOUCH_SMOOTH_GESTURE_ANDROID_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
index ffb1564ded1..5df932dfa3b 100644
--- a/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_aura.cc
+++ b/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_aura.cc
@@ -6,8 +6,8 @@
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "ui/aura/root_window.h"
-#include "ui/base/events/event.h"
-#include "ui/base/events/event_utils.h"
+#include "ui/events/event.h"
+#include "ui/events/event_utils.h"
#include "ui/gfx/transform.h"
namespace {
@@ -53,8 +53,8 @@ bool TouchSmoothScrollGestureAura::ForwardInputEvents(
return false;
RenderWidgetHostImpl* host_impl = RenderWidgetHostImpl::From(host);
- double position_delta = smooth_scroll_calculator_.GetScrollDelta(now,
- host_impl->GetSyntheticScrollMessageInterval());
+ float position_delta = synthetic_gesture_calculator_.GetDelta(now,
+ host_impl->GetSyntheticGestureMessageInterval());
if (pixels_scrolled_ == 0) {
InjectTouchEvent(location_, ui::ET_TOUCH_PRESSED, window_);
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
index 779e02d6dd0..890b1467d68 100644
--- a/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_aura.h
+++ b/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_aura.h
@@ -6,8 +6,8 @@
#define CONTENT_BROWSER_RENDERER_HOST_TOUCH_SMOOTH_SCROLL_GESTURE_
#include "base/time/time.h"
-#include "content/browser/renderer_host/smooth_scroll_calculator.h"
-#include "content/port/browser/smooth_scroll_gesture.h"
+#include "content/browser/renderer_host/synthetic_gesture_calculator.h"
+#include "content/port/browser/synthetic_gesture.h"
#include "ui/gfx/point.h"
namespace aura {
@@ -16,7 +16,7 @@ class Window;
namespace content {
-class TouchSmoothScrollGestureAura : public SmoothScrollGesture {
+class TouchSmoothScrollGestureAura : public SyntheticGesture {
public:
TouchSmoothScrollGestureAura(bool scroll_down,
int pixels_to_scroll,
@@ -35,7 +35,7 @@ class TouchSmoothScrollGestureAura : public SmoothScrollGesture {
int pixels_scrolled_;
gfx::Point location_;
aura::Window* window_;
- SmoothScrollCalculator smooth_scroll_calculator_;
+ SyntheticGestureCalculator synthetic_gesture_calculator_;
DISALLOW_COPY_AND_ASSIGN(TouchSmoothScrollGestureAura);
};
diff --git a/chromium/content/browser/renderer_host/ui_events_helper.cc b/chromium/content/browser/renderer_host/ui_events_helper.cc
index 89242946cab..78a7bff4f74 100644
--- a/chromium/content/browser/renderer_host/ui_events_helper.cc
+++ b/chromium/content/browser/renderer_host/ui_events_helper.cc
@@ -5,8 +5,8 @@
#include "content/browser/renderer_host/ui_events_helper.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "ui/base/events/event.h"
-#include "ui/base/events/event_constants.h"
+#include "ui/events/event.h"
+#include "ui/events/event_constants.h"
namespace {
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 8931f1f5d91..6bb5e5838af 100644
--- a/chromium/content/browser/renderer_host/web_input_event_aura.cc
+++ b/chromium/content/browser/renderer_host/web_input_event_aura.cc
@@ -6,11 +6,57 @@
#include "content/browser/renderer_host/ui_events_helper.h"
#include "ui/aura/window.h"
-#include "ui/base/events/event.h"
-#include "ui/base/events/event_utils.h"
+#include "ui/events/event.h"
+#include "ui/events/event_utils.h"
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) {
+ if (windows_key_code >= ui::VKEY_A &&
+ windows_key_code <= ui::VKEY_Z) {
+ // ctrl-A ~ ctrl-Z map to \x01 ~ \x1A
+ return windows_key_code - ui::VKEY_A + 1;
+ }
+ if (shift) {
+ // following graphics chars require shift key to input.
+ switch (windows_key_code) {
+ // ctrl-@ maps to \x00 (Null byte)
+ case ui::VKEY_2:
+ return 0;
+ // ctrl-^ maps to \x1E (Record separator, Information separator two)
+ case ui::VKEY_6:
+ return 0x1E;
+ // ctrl-_ maps to \x1F (Unit separator, Information separator one)
+ case ui::VKEY_OEM_MINUS:
+ return 0x1F;
+ // Returns 0 for all other keys to avoid inputting unexpected chars.
+ default:
+ break;
+ }
+ } else {
+ switch (windows_key_code) {
+ // ctrl-[ maps to \x1B (Escape)
+ case ui::VKEY_OEM_4:
+ return 0x1B;
+ // ctrl-\ maps to \x1C (File separator, Information separator four)
+ case ui::VKEY_OEM_5:
+ return 0x1C;
+ // ctrl-] maps to \x1D (Group separator, Information separator three)
+ case ui::VKEY_OEM_6:
+ return 0x1D;
+ // ctrl-Enter maps to \x0A (Line feed)
+ case ui::VKEY_RETURN:
+ return 0x0A;
+ // Returns 0 for all other keys to avoid inputting unexpected chars.
+ default:
+ break;
+ }
+ }
+ return 0;
+}
+#endif
#if defined(OS_WIN)
WebKit::WebMouseEvent MakeUntranslatedWebMouseEventFromNativeEvent(
base::NativeEvent native_event);
@@ -21,28 +67,104 @@ WebKit::WebKeyboardEvent MakeWebKeyboardEventFromNativeEvent(
WebKit::WebGestureEvent MakeWebGestureEventFromNativeEvent(
base::NativeEvent native_event);
#elif defined(USE_X11)
-WebKit::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
- ui::ScrollEvent* event);
WebKit::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
ui::KeyEvent* event);
-WebKit::WebGestureEvent MakeWebGestureEventFromAuraEvent(
- ui::ScrollEvent* event);
-#else
+#elif defined(USE_OZONE)
+WebKit::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
+ ui::KeyEvent* event) {
+ base::NativeEvent native_event = event->native_event();
+ ui::EventType type = ui::EventTypeFromNative(native_event);
+ WebKit::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;
+ break;
+ case ui::ET_KEY_RELEASED:
+ webkit_event.type = WebKit::WebInputEvent::KeyUp;
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ if (webkit_event.modifiers & WebKit::WebInputEvent::AltKey)
+ webkit_event.isSystemKey = true;
+
+ wchar_t character = ui::KeyboardCodeFromNative(native_event);
+ webkit_event.windowsKeyCode = character;
+ webkit_event.nativeKeyCode = character;
+
+ if (webkit_event.windowsKeyCode == ui::VKEY_RETURN)
+ webkit_event.unmodifiedText[0] = '\r';
+ else
+ webkit_event.unmodifiedText[0] = character;
+
+ if (webkit_event.modifiers & WebKit::WebInputEvent::ControlKey) {
+ webkit_event.text[0] =
+ GetControlCharacter(
+ webkit_event.windowsKeyCode,
+ webkit_event.modifiers & WebKit::WebInputEvent::ShiftKey);
+ } else {
+ webkit_event.text[0] = webkit_event.unmodifiedText[0];
+ }
+
+ webkit_event.setKeyIdentifierFromWindowsKeyCode();
+
+ return webkit_event;
+}
+#endif
+#if defined(USE_X11) || defined(USE_OZONE)
WebKit::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
ui::ScrollEvent* event) {
WebKit::WebMouseWheelEvent webkit_event;
- return webkit_event;
-}
-WebKit::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
- ui::KeyEvent* event) {
- WebKit::WebKeyboardEvent webkit_event;
+ webkit_event.type = WebKit::WebInputEvent::MouseWheel;
+ webkit_event.button = WebKit::WebMouseEvent::ButtonNone;
+ webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
+ webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
+ webkit_event.hasPreciseScrollingDeltas = true;
+ webkit_event.deltaX = event->x_offset();
+ if (event->x_offset_ordinal() != 0.f && event->x_offset() != 0.f) {
+ webkit_event.accelerationRatioX =
+ event->x_offset_ordinal() / event->x_offset();
+ }
+ webkit_event.wheelTicksX = webkit_event.deltaX / kPixelsPerTick;
+ webkit_event.deltaY = event->y_offset();
+ webkit_event.wheelTicksY = webkit_event.deltaY / kPixelsPerTick;
+ if (event->y_offset_ordinal() != 0.f && event->y_offset() != 0.f) {
+ webkit_event.accelerationRatioY =
+ event->y_offset_ordinal() / event->y_offset();
+ }
return webkit_event;
}
WebKit::WebGestureEvent MakeWebGestureEventFromAuraEvent(
ui::ScrollEvent* event) {
WebKit::WebGestureEvent webkit_event;
+
+ switch (event->type()) {
+ case ui::ET_SCROLL_FLING_START:
+ webkit_event.type = WebKit::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;
+ break;
+ case ui::ET_SCROLL:
+ NOTREACHED() << "Invalid gesture type: " << event->type();
+ break;
+ default:
+ NOTREACHED() << "Unknown gesture type: " << event->type();
+ }
+
+ webkit_event.sourceDevice = WebKit::WebGestureEvent::Touchpad;
+ webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
+ webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
return webkit_event;
}
@@ -234,6 +356,7 @@ WebKit::WebMouseEvent MakeWebMouseEventFromAuraEvent(ui::MouseEvent* event) {
break;
case ui::ET_MOUSE_RELEASED:
webkit_event.type = WebKit::WebInputEvent::MouseUp;
+ webkit_event.clickCount = event->GetClickCount();
break;
case ui::ET_MOUSE_ENTERED:
case ui::ET_MOUSE_EXITED:
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 ddc59e0c46f..3c4c8945bed 100644
--- a/chromium/content/browser/renderer_host/web_input_event_aura.h
+++ b/chromium/content/browser/renderer_host/web_input_event_aura.h
@@ -22,6 +22,10 @@ namespace content {
// Used for scrolling. This matches Firefox behavior.
const int kPixelsPerTick = 53;
+#if defined(USE_X11) || defined(USE_OZONE)
+CONTENT_EXPORT WebKit::WebUChar GetControlCharacter(
+ int windows_key_code, bool shift);
+#endif
CONTENT_EXPORT WebKit::WebMouseEvent MakeWebMouseEvent(
ui::MouseEvent* event);
CONTENT_EXPORT WebKit::WebMouseWheelEvent MakeWebMouseWheelEvent(
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 0443c30dad9..818250c0dd6 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
@@ -6,11 +6,12 @@
#include "base/basictypes.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/events/event.h"
+#include "ui/events/event.h"
#if defined(USE_X11)
#include <X11/keysym.h>
#include <X11/Xlib.h>
+#include "ui/gfx/x/x11_types.h"
#include "ui/base/x/x11_util.h"
#endif
@@ -56,7 +57,7 @@ TEST(WebInputEventAuraTest, TestMakeWebKeyboardEventWindowsKeyCode) {
ui::VKEY_CONTROL,
0, // X does not set ControlMask for KeyPress.
&xev);
- xev.xkey.keycode = XKeysymToKeycode(ui::GetXDisplay(), XK_Control_L);
+ xev.xkey.keycode = XKeysymToKeycode(gfx::GetXDisplay(), XK_Control_L);
ui::KeyEvent event(&xev, false /* is_char */);
WebKit::WebKeyboardEvent webkit_event = MakeWebKeyboardEvent(&event);
// ui::VKEY_LCONTROL, instead of ui::VKEY_CONTROL, should be filled.
@@ -68,7 +69,7 @@ TEST(WebInputEventAuraTest, TestMakeWebKeyboardEventWindowsKeyCode) {
ui::VKEY_CONTROL,
0, // X does not set ControlMask for KeyPress.
&xev);
- xev.xkey.keycode = XKeysymToKeycode(ui::GetXDisplay(), XK_Control_R);
+ xev.xkey.keycode = XKeysymToKeycode(gfx::GetXDisplay(), XK_Control_R);
ui::KeyEvent event(&xev, false /* is_char */);
WebKit::WebKeyboardEvent webkit_event = MakeWebKeyboardEvent(&event);
// ui::VKEY_RCONTROL, instead of ui::VKEY_CONTROL, should be filled.
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 fdde17edc7b..76ae55f5f19 100644
--- a/chromium/content/browser/renderer_host/web_input_event_aurax11.cc
+++ b/chromium/content/browser/renderer_host/web_input_event_aurax11.cc
@@ -45,10 +45,10 @@
#include "base/event_types.h"
#include "base/logging.h"
#include "content/browser/renderer_host/ui_events_helper.h"
-#include "ui/base/events/event.h"
-#include "ui/base/events/event_constants.h"
-#include "ui/base/keycodes/keyboard_code_conversion_x.h"
-#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/events/event.h"
+#include "ui/events/event_constants.h"
+#include "ui/events/keycodes/keyboard_code_conversion_x.h"
+#include "ui/events/keycodes/keyboard_codes.h"
namespace content {
@@ -87,106 +87,8 @@ int XKeyEventToWindowsKeyCode(XKeyEvent* event) {
return windows_key_code;
}
-// From third_party/WebKit/Source/web/gtk/WebInputEventFactory.cpp:
-WebKit::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
- return windows_key_code - ui::VKEY_A + 1;
- }
- if (shift) {
- // following graphics chars require shift key to input.
- switch (windows_key_code) {
- // ctrl-@ maps to \x00 (Null byte)
- case ui::VKEY_2:
- return 0;
- // ctrl-^ maps to \x1E (Record separator, Information separator two)
- case ui::VKEY_6:
- return 0x1E;
- // ctrl-_ maps to \x1F (Unit separator, Information separator one)
- case ui::VKEY_OEM_MINUS:
- return 0x1F;
- // Returns 0 for all other keys to avoid inputting unexpected chars.
- default:
- break;
- }
- } else {
- switch (windows_key_code) {
- // ctrl-[ maps to \x1B (Escape)
- case ui::VKEY_OEM_4:
- return 0x1B;
- // ctrl-\ maps to \x1C (File separator, Information separator four)
- case ui::VKEY_OEM_5:
- return 0x1C;
- // ctrl-] maps to \x1D (Group separator, Information separator three)
- case ui::VKEY_OEM_6:
- return 0x1D;
- // ctrl-Enter maps to \x0A (Line feed)
- case ui::VKEY_RETURN:
- return 0x0A;
- // Returns 0 for all other keys to avoid inputting unexpected chars.
- default:
- break;
- }
- }
- return 0;
-}
-
} // namespace
-WebKit::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
- ui::ScrollEvent* event) {
- WebKit::WebMouseWheelEvent webkit_event;
-
- webkit_event.type = WebKit::WebInputEvent::MouseWheel;
- webkit_event.button = WebKit::WebMouseEvent::ButtonNone;
- webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
- webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
- webkit_event.hasPreciseScrollingDeltas = true;
- webkit_event.deltaX = event->x_offset();
- if (event->x_offset_ordinal() != 0.f && event->x_offset() != 0.f) {
- webkit_event.accelerationRatioX =
- event->x_offset_ordinal() / event->x_offset();
- }
- webkit_event.wheelTicksX = webkit_event.deltaX / kPixelsPerTick;
- webkit_event.deltaY = event->y_offset();
- webkit_event.wheelTicksY = webkit_event.deltaY / kPixelsPerTick;
- if (event->y_offset_ordinal() != 0.f && event->y_offset() != 0.f) {
- webkit_event.accelerationRatioY =
- event->y_offset_ordinal() / event->y_offset();
- }
-
- return webkit_event;
-}
-
-// NOTE: ui::ScrollEvent instances come from the touchpad.
-WebKit::WebGestureEvent MakeWebGestureEventFromAuraEvent(
- ui::ScrollEvent* event) {
- WebKit::WebGestureEvent webkit_event;
-
- switch (event->type()) {
- case ui::ET_SCROLL_FLING_START:
- webkit_event.type = WebKit::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;
- break;
- case ui::ET_SCROLL:
- NOTREACHED() << "Invalid gesture type: " << event->type();
- break;
- default:
- NOTREACHED() << "Unknown gesture type: " << event->type();
- }
-
- webkit_event.sourceDevice = WebKit::WebGestureEvent::Touchpad;
- webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
- webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
-
- return webkit_event;
-}
-
WebKit::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
ui::KeyEvent* event) {
base::NativeEvent native_event = event->native_event();
diff --git a/chromium/content/browser/resources/indexed_db/indexeddb_internals.css b/chromium/content/browser/resources/indexed_db/indexeddb_internals.css
index 76653f0921c..c52f5ff9754 100644
--- a/chromium/content/browser/resources/indexed_db/indexeddb_internals.css
+++ b/chromium/content/browser/resources/indexed_db/indexeddb_internals.css
@@ -48,22 +48,55 @@
font-weight: bold;
}
+.indexeddb-transaction-list {
+ margin-left: 10px;
+ border-collapse: collapse;
+}
+
+.indexeddb-transaction-list th,
+.indexeddb-transaction-list td {
+ padding: 2px 10px;
+ min-width: 50px;
+ max-width: 75px;
+}
+
+td.indexeddb-transaction-scope {
+ min-width: 200px;
+ max-width: 500px;
+}
+
+.indexeddb-transaction-list th {
+ background-color: rgb(249, 249, 249);
+ border: 1px solid rgb(156, 194, 239);
+ font-weight: normal;
+ text-align: left;
+}
+
.indexeddb-transaction {
background-color: rgb(235, 239, 249);
- margin: 4px 0;
- border-radius: 4px;
- padding: 2px;
- position: relative;
+ border-bottom: 2px solid white;
}
+.indexeddb-transaction.created {
+ font-weight: italic;
+}
+.indexeddb-transaction.started {
+ font-weight: bold;
+}
.indexeddb-transaction.running {
font-weight: bold;
}
+.indexeddb-transaction.blocked {
+}
-.indexeddb-transaction-mode,
-.indexeddb-transaction-scope,
-.indexeddb-transaction-state {
- margin: 0 8px;
+.indexeddb-transaction.started .indexeddb-transaction-state {
+ background-color: rgb(249, 249, 235);
+}
+.indexeddb-transaction.running .indexeddb-transaction-state {
+ background-color: rgb(235, 249, 235);
+}
+.indexeddb-transaction.blocked .indexeddb-transaction-state {
+ background-color: rgb(249, 235, 235);
}
.controls a {
diff --git a/chromium/content/browser/resources/indexed_db/indexeddb_internals.html b/chromium/content/browser/resources/indexed_db/indexeddb_internals.html
index 153aef1aa11..781fcb0fcec 100644
--- a/chromium/content/browser/resources/indexed_db/indexeddb_internals.html
+++ b/chromium/content/browser/resources/indexed_db/indexeddb_internals.html
@@ -84,16 +84,85 @@
</span>
</div>
- <div class="indexeddb-transaction"
- jsselect="$this.transactions"
- jseval="this.classList.add($this.running ? 'running' : 'waiting')">
- <span>Transaction:</span>
- <span class="indexeddb-transaction-mode" jscontent="mode"></span>
- <span class="indexeddb-transaction-scope" jsdisplay="scope">
- <span>scope:</span> <span jscontent="'[ ' + scope.join(', ') + ' ]'"></span>
- </span>
- <span class="indexeddb-transaction-state"
- jscontent="running ? '(running)' : '(blocked)'"></span>
+ <div jsdisplay="$this.transactions &amp;&amp;
+ $this.transactions.length">
+ <span>Transactions:</span>
+
+ <table class="indexeddb-transaction-list">
+ <tbody>
+ <tr>
+ <th title="Process ID of the tab or SharedWorker that created the transaction">
+ Process ID
+ </th>
+ <th title="Transaction ID (unique within Process)">
+ ID
+ </th>
+ <th title="Type of transaction">
+ Mode
+ </th>
+ <th title="Names of object stores used by the transaction">
+ Scope
+ </th>
+ <th title="Number of requests that have been executed">
+ Completed Requests
+ </th>
+ <th title="Number of requests that have not yet been executed">
+ Pending Requests
+ </th>
+ <th title="Time since transaction creation">
+ Age (ms)
+ </th>
+ <th title="Time since transaction started">
+ Runtime (ms)
+ </th>
+ <th title="Status in the transaction queue">
+ Status
+ </th>
+ </tr>
+ <tr class="indexeddb-transaction"
+ jsselect="$this.transactions"
+ jseval="this.classList.add($this.status)">
+
+ <td class="indexeddb-transaction-pid"
+ jscontent="pid">
+ </td>
+
+ <td class="indexeddb-transaction-tid"
+ jscontent="tid">
+ </td>
+
+ <td class="indexeddb-transaction-mode"
+ jscontent="mode">
+ </td>
+
+ <td class="indexeddb-transaction-scope"
+ jscontent="'[ ' + scope.join(', ') + ' ]'">
+ </td>
+
+ <td class="indexeddb-transaction-requests-complete"
+ jscontent="tasks_completed">
+ </td>
+
+ <td class="indexeddb-transaction-requests-pending"
+ jscontent="tasks_scheduled - tasks_completed">
+ </td>
+
+ <td class="indexeddb-transaction-age"
+ jscontent="Math.round(age)">
+ </td>
+
+ <td class="indexeddb-transaction-age">
+ <span jsdisplay="status == 'started' || status == 'running'"
+ jscontent="Math.round(runtime)">
+ </span>
+ </td>
+
+ <td class="indexeddb-transaction-state"
+ jscontent="status">
+ </td>
+ </tr>
+ </tbody>
+ </table>
</div>
</div>
</div>
diff --git a/chromium/content/browser/resources/media/cache_entry.js b/chromium/content/browser/resources/media/cache_entry.js
index 275a8c74a50..e4b3f0d3e05 100644
--- a/chromium/content/browser/resources/media/cache_entry.js
+++ b/chromium/content/browser/resources/media/cache_entry.js
@@ -176,6 +176,12 @@ cr.define('media', function() {
* this file.
*/
generateDetails: function() {
+ function makeElement(tag, content) {
+ var toReturn = document.createElement(tag);
+ toReturn.textContent = content;
+ return toReturn;
+ }
+
this.details_.id = this.key;
this.summaryText_.textContent = this.key || 'Unknown File';
@@ -188,8 +194,8 @@ cr.define('media', function() {
this.detailTable_.appendChild(body);
var headerRow = document.createElement('tr');
- headerRow.appendChild(media.makeElement('th', 'Read From Cache'));
- headerRow.appendChild(media.makeElement('th', 'Written To Cache'));
+ headerRow.appendChild(makeElement('th', 'Read From Cache'));
+ headerRow.appendChild(makeElement('th', 'Written To Cache'));
header.appendChild(headerRow);
var footerRow = document.createElement('tr');
@@ -209,8 +215,8 @@ cr.define('media', function() {
var length = Math.max(read.length, written.length);
for (var i = 0; i < length; i++) {
var row = document.createElement('tr');
- row.appendChild(media.makeElement('td', read[i] || ''));
- row.appendChild(media.makeElement('td', written[i] || ''));
+ row.appendChild(makeElement('td', read[i] || ''));
+ row.appendChild(makeElement('td', written[i] || ''));
body.appendChild(row);
}
diff --git a/chromium/content/browser/resources/media/client_renderer.js b/chromium/content/browser/resources/media/client_renderer.js
new file mode 100644
index 00000000000..cac70e8b839
--- /dev/null
+++ b/chromium/content/browser/resources/media/client_renderer.js
@@ -0,0 +1,306 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+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.graphElement = document.getElementById('graphs');
+
+ this.selectedPlayer = null;
+ this.selectedStream = null;
+
+ this.selectedPlayerLogIndex = 0;
+
+ this.filterFunction = function() { return true; };
+ this.filterText = document.getElementById('filter-text');
+ this.filterText.onkeyup = this.onTextChange_.bind(this);
+
+ this.bufferCanvas = document.createElement('canvas');
+ this.bufferCanvas.width = media.BAR_WIDTH;
+ this.bufferCanvas.height = media.BAR_HEIGHT;
+
+ this.clipboardTextarea = document.getElementById('clipboard-textarea');
+ this.clipboardButton = document.getElementById('copy-button');
+ this.clipboardButton.onclick = this.copyToClipboard_.bind(this);
+ };
+
+ function removeChildren(element) {
+ while (element.hasChildNodes()) {
+ element.removeChild(element.lastChild);
+ }
+ };
+
+ function createButton(text, select_cb) {
+ var button = document.createElement('button');
+
+ button.appendChild(document.createTextNode(text));
+ button.onclick = function() {
+ select_cb();
+ };
+
+ return button;
+ };
+
+ ClientRenderer.prototype = {
+ audioStreamAdded: function(audioStreams, audioStreamAdded) {
+ this.redrawAudioStreamList_(audioStreams);
+ },
+
+ audioStreamUpdated: function(audioStreams, stream, key, value) {
+ if (stream === this.selectedStream) {
+ this.drawProperties_(stream);
+ }
+ },
+
+ audioStreamRemoved: function(audioStreams, audioStreamRemoved) {
+ this.redrawAudioStreamList_(audioStreams);
+ },
+
+ /**
+ * Called when a player is added to the collection.
+ * @param players The entire map of id -> player.
+ * @param player_added The player that is added.
+ */
+ playerAdded: function(players, playerAdded) {
+ this.redrawPlayerList_(players);
+ },
+
+ /**
+ * Called when a playre is removed from the collection.
+ * @param players The entire map of id -> player.
+ * @param player_added The player that was removed.
+ */
+ playerRemoved: function(players, playerRemoved) {
+ this.redrawPlayerList_(players);
+ },
+
+ /**
+ * Called when a property on a player is changed.
+ * @param players The entire map of id -> player.
+ * @param player The player that had its property changed.
+ * @param key The name of the property that was changed.
+ * @param value The new value of the property.
+ */
+ playerUpdated: function(players, player, key, value) {
+ if (player === this.selectedPlayer) {
+ this.drawProperties_(player.properties);
+ this.drawLog_();
+ this.drawGraphs_();
+ }
+ if (key === 'name' || key === 'url') {
+ this.redrawPlayerList_(players);
+ }
+ },
+
+ redrawAudioStreamList_: function(streams) {
+ removeChildren(this.audioStreamListElement);
+
+ for (id in streams) {
+ var li = document.createElement('li');
+ li.appendChild(createButton(
+ id, this.selectAudioStream_.bind(this, streams[id])));
+ this.audioStreamListElement.appendChild(li);
+ }
+ },
+
+ selectAudioStream_: function(audioStream) {
+ this.selectedStream = audioStream;
+ this.selectedPlayer = null;
+ this.drawProperties_(audioStream);
+ removeChildren(this.logTable.querySelector('tbody'));
+ removeChildren(this.graphElement);
+ },
+
+ redrawPlayerList_: function(players) {
+ removeChildren(this.playerListElement);
+
+ for (id in players) {
+ var li = document.createElement('li');
+ var player = players[id];
+ var usableName = player.properties.name ||
+ player.properties.url ||
+ 'player ' + player.id;
+
+ li.appendChild(createButton(
+ usableName, this.selectPlayer_.bind(this, player)));
+ this.playerListElement.appendChild(li);
+ }
+ },
+
+ selectPlayer_: function(player) {
+ this.selectedPlayer = player;
+ this.selectedPlayerLogIndex = 0;
+ this.selectedStream = null;
+ this.drawProperties_(player.properties);
+
+ removeChildren(this.logTable.querySelector('tbody'));
+ removeChildren(this.graphElement);
+ this.drawLog_();
+ this.drawGraphs_();
+ },
+
+ drawProperties_: function(propertyMap) {
+ removeChildren(this.propertiesTable);
+
+ for (key in propertyMap) {
+ var value = propertyMap[key];
+
+ var row = this.propertiesTable.insertRow(-1);
+ var keyCell = row.insertCell(-1);
+ var valueCell = row.insertCell(-1);
+
+ keyCell.appendChild(document.createTextNode(key));
+ valueCell.appendChild(document.createTextNode(value));
+ }
+ },
+
+ appendEventToLog_: function(event) {
+ if (this.filterFunction(event.key)) {
+ var row = this.logTable.querySelector('tbody').insertRow(-1);
+
+ row.insertCell(-1).appendChild(document.createTextNode(
+ util.millisecondsToString(event.time)));
+ row.insertCell(-1).appendChild(document.createTextNode(event.key));
+ row.insertCell(-1).appendChild(document.createTextNode(event.value));
+ }
+ },
+
+ drawLog_: function() {
+ var toDraw = this.selectedPlayer.allEvents.slice(
+ this.selectedPlayerLogIndex);
+ toDraw.forEach(this.appendEventToLog_.bind(this));
+ this.selectedPlayerLogIndex = this.selectedPlayer.allEvents.length;
+ },
+
+ drawGraphs_: function() {
+ function addToGraphs(name, graph, graphElement) {
+ var li = document.createElement('li');
+ li.appendChild(graph);
+ li.appendChild(document.createTextNode(name));
+ graphElement.appendChild(li);
+ }
+
+ var url = this.selectedPlayer.properties.url;
+ if (!url) {
+ return;
+ }
+
+ var cache = media.cacheForUrl(url);
+
+ var player = this.selectedPlayer;
+ var props = player.properties;
+
+ var cacheExists = false;
+ var bufferExists = false;
+
+ if (props['buffer_start'] !== undefined &&
+ props['buffer_current'] !== undefined &&
+ props['buffer_end'] !== undefined &&
+ props['total_bytes'] !== undefined) {
+ this.drawBufferGraph_(props['buffer_start'],
+ props['buffer_current'],
+ props['buffer_end'],
+ props['total_bytes']);
+ bufferExists = true;
+ }
+
+ if (cache) {
+ if (player.properties['total_bytes']) {
+ cache.size = Number(player.properties['total_bytes']);
+ }
+ cache.generateDetails();
+ cacheExists = true;
+
+ }
+
+ if (!this.graphElement.hasChildNodes()) {
+ if (bufferExists) {
+ addToGraphs('buffer', this.bufferCanvas, this.graphElement);
+ }
+ if (cacheExists) {
+ addToGraphs('cache read', cache.readCanvas, this.graphElement);
+ addToGraphs('cache write', cache.writeCanvas, this.graphElement);
+ }
+ }
+ },
+
+ drawBufferGraph_: function(start, current, end, size) {
+ var ctx = this.bufferCanvas.getContext('2d');
+ var width = this.bufferCanvas.width;
+ var height = this.bufferCanvas.height;
+ ctx.fillStyle = '#aaa';
+ ctx.fillRect(0, 0, width, height);
+
+ var scale_factor = width / size;
+ var left = start * scale_factor;
+ var middle = current * scale_factor;
+ var right = end * scale_factor;
+
+ ctx.fillStyle = '#a0a';
+ ctx.fillRect(left, 0, middle - left, height);
+ ctx.fillStyle = '#aa0';
+ ctx.fillRect(middle, 0, right - middle, height);
+ },
+
+ copyToClipboard_: function() {
+ var properties = this.selectedStream ||
+ this.selectedPlayer.properties || false;
+ if (!properties) {
+ return;
+ }
+ var stringBuffer = [];
+
+ for (var key in properties) {
+ var value = properties[key];
+ stringBuffer.push(key.toString());
+ stringBuffer.push(': ');
+ stringBuffer.push(value.toString());
+ stringBuffer.push('\n');
+ }
+
+ this.clipboardTextarea.value = stringBuffer.join('');
+ this.clipboardTextarea.classList.remove('hidden');
+ 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) {
+ setTimeout(function(element) {
+ event.target.classList.add('hidden');
+ }, 0);
+ };
+ },
+
+ onTextChange_: function(event) {
+ var text = this.filterText.value.toLowerCase();
+ var parts = text.split(',').map(function(part) {
+ return part.trim();
+ }).filter(function(part) {
+ return part.trim().length > 0;
+ });
+
+ this.filterFunction = function(text) {
+ text = text.toLowerCase();
+ return parts.length === 0 || parts.some(function(part) {
+ return text.indexOf(part) != -1;
+ });
+ };
+
+ if (this.selectedPlayer) {
+ removeChildren(this.logTable.querySelector('tbody'));
+ this.selectedPlayerLogIndex = 0;
+ this.drawLog_();
+ }
+ },
+ };
+
+ return ClientRenderer;
+})();
diff --git a/chromium/content/browser/resources/media/event_list.js b/chromium/content/browser/resources/media/event_list.js
deleted file mode 100644
index df4d4273063..00000000000
--- a/chromium/content/browser/resources/media/event_list.js
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-cr.define('media', function() {
- 'use strict';
-
- /**
- * This class holds a list of MediaLogEvents.
- * It inherits from <li> and contains a tabular list of said events,
- * the time at which they occurred, and their parameters.
- */
- var EventList = cr.ui.define('li');
-
- EventList.prototype = {
- __proto__: HTMLLIElement.prototype,
- startTime_: null,
-
- /**
- * Decorate this list item as an EventList.
- */
- decorate: function() {
- this.table_ = document.createElement('table');
- var details = document.createElement('details');
- var summary = media.makeElement('summary', 'Log:');
- details.appendChild(summary);
- details.appendChild(this.table_);
- this.appendChild(details);
-
- var hRow = document.createElement('tr');
- hRow.appendChild(media.makeElement('th', 'Time:'));
- hRow.appendChild(media.makeElement('th', 'Event:'));
- hRow.appendChild(media.makeElement('th', 'Parameters:'));
- var header = document.createElement('thead');
- header.appendChild(hRow);
- this.table_.appendChild(header);
- },
-
- /**
- * Add an event to the list. It is stored as a new row in this.table_.
- * @param {Object} event The MediaLogEvent that has occurred.
- */
- addEvent: function(event) {
- this.startTime_ = this.startTime_ || event.ticksMillis;
- var normalizedTicksMillis = event.ticksMillis - this.startTime_;
-
- var row = document.createElement('tr');
- row.appendChild(media.makeElement(
- 'td', normalizedTicksMillis.toFixed(1)));
- row.appendChild(media.makeElement('td', event.type));
- var params = [];
- for (var key in event.params) {
- params.push(key + ': ' + event.params[key]);
- }
-
- row.appendChild(media.makeElement('td', params.join(', ')));
- this.table_.appendChild(row);
- }
- };
-
- return {
- EventList: EventList
- };
-});
diff --git a/chromium/content/browser/resources/media/item_store.js b/chromium/content/browser/resources/media/item_store.js
deleted file mode 100644
index a6e3a6c4577..00000000000
--- a/chromium/content/browser/resources/media/item_store.js
+++ /dev/null
@@ -1,70 +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.
-
-cr.define('media', function() {
-
- /**
- * This class stores hashes by their id field and provides basic methods for
- * iterating over the collection.
- * @constructor
- */
- function ItemStore() {
- this.items_ = {};
- }
-
- ItemStore.prototype = {
- /**
- * Get a sorted list of item ids.
- * @return {Array} A sorted array of ids.
- */
- ids: function() {
- var ids = [];
- for (var i in this.items_)
- ids.push(i);
- return ids.sort();
- },
-
- /**
- * Add an item to the store.
- * @param {Object} item The item to be added.
- * @param {string} item.id The id of the item.
- */
- addItem: function(item) {
- this.items_[item.id] = item;
- },
-
- /**
- * Add a dictionary of items to the store.
- * @param {Object} items A dictionary of individual items. The keys are
- * irrelevant but each must have an id field.
- */
- addItems: function(items) {
- for (id in items)
- this.addItem(items[id]);
- },
-
- /**
- * Remove an item from the store.
- * @param {string} id The id of the item to be removed.
- */
- removeItem: function(id) {
- delete this.items_[id];
- },
-
- /**
- * Map this itemStore to an Array. Items are sorted by id.
- * @param {function(*)} mapper The mapping function applied to each item.
- * @return {Array} An array of mapped items.
- */
- map: function(mapper) {
- var items = this.items_;
- var ids = this.ids();
- return ids.map(function(id) { return mapper(items[id]); });
- }
- };
-
- return {
- ItemStore: ItemStore
- };
-});
diff --git a/chromium/content/browser/resources/media/main.js b/chromium/content/browser/resources/media/main.js
new file mode 100644
index 00000000000..14b9918a2de
--- /dev/null
+++ b/chromium/content/browser/resources/media/main.js
@@ -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.
+
+/**
+ * A global object that gets used by the C++ interface.
+ */
+var media = (function() {
+ 'use strict';
+
+ var manager = null;
+
+ // A number->string mapping that is populated through the backend that
+ // describes the phase that the network entity is in.
+ var eventPhases = {};
+
+ // A number->string mapping that is populated through the backend that
+ // describes the type of event sent from the network.
+ var eventTypes = {};
+
+ // A mapping of number->CacheEntry where the number is a unique id for that
+ // network request.
+ var cacheEntries = {};
+
+ // A mapping of url->CacheEntity where the url is the url of the resource.
+ var cacheEntriesByKey = {};
+
+ var requrestURLs = {};
+
+ var media = {
+ BAR_WIDTH: 200,
+ BAR_HEIGHT: 25
+ };
+
+ /**
+ * Users of |media| must call initialize prior to calling other methods.
+ */
+ media.initialize = function(theManager) {
+ manager = theManager;
+ };
+
+ media.onReceiveEverything = function(everything) {
+ for (var key in everything.audio_streams) {
+ media.updateAudioStream(everything.audio_streams[key]);
+ }
+ };
+
+ media.onReceiveConstants = function(constants) {
+ for (var key in constants.eventTypes) {
+ var value = constants.eventTypes[key];
+ eventTypes[value] = key;
+ }
+
+ for (var key in constants.eventPhases) {
+ var value = constants.eventPhases[key];
+ eventPhases[value] = key;
+ }
+ };
+
+ media.cacheForUrl = function(url) {
+ return cacheEntriesByKey[url];
+ };
+
+ media.onNetUpdate = function(updates) {
+ updates.forEach(function(update) {
+ var id = update.source.id;
+ if (!cacheEntries[id])
+ cacheEntries[id] = new media.CacheEntry;
+
+ switch (eventPhases[update.phase] + '.' + eventTypes[update.type]) {
+ case 'PHASE_BEGIN.DISK_CACHE_ENTRY_IMPL':
+ var key = update.params.key;
+
+ // Merge this source with anything we already know about this key.
+ if (cacheEntriesByKey[key]) {
+ cacheEntriesByKey[key].merge(cacheEntries[id]);
+ cacheEntries[id] = cacheEntriesByKey[key];
+ } else {
+ cacheEntriesByKey[key] = cacheEntries[id];
+ }
+ cacheEntriesByKey[key].key = key;
+ break;
+
+ case 'PHASE_BEGIN.SPARSE_READ':
+ cacheEntries[id].readBytes(update.params.offset,
+ update.params.buff_len);
+ cacheEntries[id].sparse = true;
+ break;
+
+ case 'PHASE_BEGIN.SPARSE_WRITE':
+ cacheEntries[id].writeBytes(update.params.offset,
+ update.params.buff_len);
+ cacheEntries[id].sparse = true;
+ break;
+
+ case 'PHASE_BEGIN.URL_REQUEST_START_JOB':
+ requrestURLs[update.source.id] = update.params.url;
+ break;
+
+ case 'PHASE_NONE.HTTP_TRANSACTION_READ_RESPONSE_HEADERS':
+ // Record the total size of the file if this was a range request.
+ var range = /content-range:\s*bytes\s*\d+-\d+\/(\d+)/i.exec(
+ update.params.headers);
+ var key = requrestURLs[update.source.id];
+ delete requrestURLs[update.source.id];
+ if (range && key) {
+ if (!cacheEntriesByKey[key]) {
+ cacheEntriesByKey[key] = new media.CacheEntry;
+ cacheEntriesByKey[key].key = key;
+ }
+ cacheEntriesByKey[key].size = range[1];
+ }
+ break;
+ }
+ });
+ };
+
+ media.onRendererTerminated = function(renderId) {
+ util.object.forEach(manager.players_, function(playerInfo, id) {
+ if (playerInfo.properties['render_id'] == renderId) {
+ manager.removePlayer(id);
+ }
+ });
+ };
+
+ // 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;
+ case 'closed':
+ manager.removeAudioStream(event.id);
+ 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);
+ };
+
+ media.onMediaEvent = function(event) {
+ var source = event.renderer + ':' + event.player;
+
+ // Although this gets called on every event, there is nothing we can do
+ // because there is no onOpen event.
+ media.onPlayerOpen(source);
+ manager.updatePlayerInfoNoRecord(
+ source, event.ticksMillis, 'render_id', event.renderer);
+ manager.updatePlayerInfoNoRecord(
+ source, event.ticksMillis, 'player_id', event.player);
+
+ var propertyCount = 0;
+ util.object.forEach(event.params, function(value, key) {
+ key = key.trim();
+
+ // These keys get spammed *a lot*, so put them on the display
+ // but don't log list.
+ if (key === 'buffer_start' ||
+ key === 'buffer_end' ||
+ key === 'buffer_current' ||
+ key === 'is_downloading_data') {
+ manager.updatePlayerInfoNoRecord(
+ source, event.ticksMillis, key, value);
+ } else {
+ manager.updatePlayerInfo(source, event.ticksMillis, key, value);
+ }
+ propertyCount += 1;
+ });
+
+ if (propertyCount === 0) {
+ manager.updatePlayerInfo(
+ source, event.ticksMillis, 'EVENT', event.type);
+ }
+ };
+
+ // |chrome| is not defined during tests.
+ if (window.chrome && window.chrome.send) {
+ chrome.send('getEverything');
+ }
+ return media;
+}());
diff --git a/chromium/content/browser/resources/media/manager.js b/chromium/content/browser/resources/media/manager.js
new file mode 100644
index 00000000000..1ba130181e5
--- /dev/null
+++ b/chromium/content/browser/resources/media/manager.js
@@ -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.
+
+/**
+ * @fileoverview Keeps track of all the existing PlayerInfo and
+ * audio stream objects and is the entry-point for messages from the backend.
+ *
+ * The events captured by Manager (add, remove, update) are relayed
+ * to the clientRenderer which it can choose to use to modify the UI.
+ */
+var Manager = (function() {
+ 'use strict';
+
+ function Manager(clientRenderer) {
+ this.players_ = {};
+ this.audioStreams_ = {};
+ 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.
+ */
+ updateAudioStream: function(id, properties) {
+ for (var key in properties) {
+ this.audioStreams_[id][key] = properties[key];
+ }
+ this.clientRenderer_.audioStreamAdded(
+ this.audioStreams_, this.audioStreams_[id]);
+ },
+
+ /**
+ * 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];
+ },
+
+
+ /**
+ * Adds a player to the list of players to manage.
+ */
+ addPlayer: function(id) {
+ if (this.players_[id]) {
+ return;
+ }
+ // Make the PlayerProperty and add it to the mapping
+ this.players_[id] = new PlayerInfo(id);
+ this.clientRenderer_.playerAdded(this.players_, this.players_[id]);
+ },
+
+ /**
+ * Attempts to remove a player from the UI.
+ * @param id The ID of the player to remove.
+ */
+ removePlayer: function(id) {
+ delete this.players_[id];
+ this.clientRenderer_.playerRemoved(this.players_, this.players_[id]);
+ },
+
+ updatePlayerInfoNoRecord: function(id, timestamp, key, value) {
+ if (!this.players_[id]) {
+ console.error('[updatePlayerInfo] Id ' + id + ' does not exist');
+ return;
+ }
+
+ this.players_[id].addPropertyNoRecord(timestamp, key, value);
+ this.clientRenderer_.playerUpdated(this.players_,
+ this.players_[id],
+ key,
+ value);
+ },
+
+ /**
+ *
+ * @param id The unique ID that identifies the player to be updated.
+ * @param timestamp The timestamp of when the change occured. This
+ * timestamp is *not* normalized.
+ * @param key The name of the property to be added/changed.
+ * @param value The value of the property.
+ */
+ updatePlayerInfo: function(id, timestamp, key, value) {
+ if (!this.players_[id]) {
+ console.error('[updatePlayerInfo] Id ' + id + ' does not exist');
+ return;
+ }
+
+ this.players_[id].addProperty(timestamp, key, value);
+ this.clientRenderer_.playerUpdated(this.players_,
+ this.players_[id],
+ key,
+ value);
+ }
+ };
+
+ return Manager;
+}());
diff --git a/chromium/content/browser/resources/media/media_internals.css b/chromium/content/browser/resources/media/media_internals.css
index d83b6b71eeb..9e6ab7608f2 100644
--- a/chromium/content/browser/resources/media/media_internals.css
+++ b/chromium/content/browser/resources/media/media_internals.css
@@ -1,83 +1,108 @@
-/* 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. */
-body {
- font-family: sans-serif;
-}
+html,
+body,
+#container {
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ height: 100%;
-h2 {
- margin: 15px 0 5px 0;
+ font-family: 'Lucida Grande', sans-serif;
}
-ul,
-p,
-canvas {
- margin: 0;
+table {
+ border-collapse: collapse;
}
-
-[hidden] {
- display: none !important;
+td {
+ border: 1px solid black;
+ word-wrap: break-word;
+ max-width: 200px;
}
-
-#media-players td,
-#media-players th {
- padding: 0 10px;
+thead {
+ color: rgb(50,50,50);
+ font-size: 1.1em;
}
-.audio-stream[status='created'] {
- color: blue;
+h1,
+h2,
+h3 {
+ color: rgb(50,50,50);
}
-.audio-stream[status='closed'] {
- text-decoration: line-through;
+#container {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ justify-content: space-between;
+ align-items: flex-start;
+ align-content: stretch;
}
-.audio-stream[status='error'] {
- color: red;
+#container > * {
+ padding: 0;
+ padding-left: 25px;
+ margin: 0;
}
-#cache-entries ul,
-#media-players ul,
-#media-players {
- list-style-type: none;
+#list-wrapper {
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ align-items: flex-start;
+ align-content: stretch;
}
-.cache-entry {
- margin: 0 0 5px 0;
+#player-list-wrapper,
+#audio-stream-list-wrapper {
+ flex-grow: 1;
+ align-self: stretch;
+ min-width: 200px;
+ max-width: 200px;
+ overflow: auto;
}
-.cache-entry-controls {
- font-size: smaller;
+#player-list-wrapper ul,
+#player-list-wrapper li,
+#audio-stream-list-wrapper ul,
+#audio-stream-list-wrapper li {
+ margin: 0;
+ padding: 0;
+ list-style-type: none;
}
-
-.cache-table {
- table-layout: fixed;
- width: 500px;
+#list-wrapper button {
+ margin: 0;
+ padding: 0;
+ width: 170px;
}
-thead {
- text-align: left;
+#property-wrapper,
+#log-wrapper {
+ display:block;
+ flex-grow: 0.5;
+ align-self: stretch;
+ overflow: auto;
}
-tfoot {
- text-align: right;
+#log-wrapper > thead {
+ position: fixed;
}
-.buffered {
- display: table;
+#graphs li {
+ list-style-type: none;
}
-.buffered > div {
- display: table-row;
-}
+#clipboard-textarea {
+ position: absolute;
+ width: 50%;
+ height: 50%;
-.buffered > div > div {
- display: table-cell;
- vertical-align: bottom;
+ left: 25%;
+ top: 25%;
}
-.buffered > div > div:first-child {
- font-weight: bold;
- padding-right: 2px;
+.hidden {
+ display: none;
}
diff --git a/chromium/content/browser/resources/media/media_internals.html b/chromium/content/browser/resources/media/media_internals.html
index 05d321f0ac7..6bfc48198d4 100644
--- a/chromium/content/browser/resources/media/media_internals.html
+++ b/chromium/content/browser/resources/media/media_internals.html
@@ -1,28 +1,57 @@
-<!DOCTYPE HTML>
-<html i18n-values="dir:textdirection;">
<!--
-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.
-->
- <head>
- <link rel="stylesheet" href="media_internals.css">
- <script src="chrome://resources/js/cr.js"></script>
- <script src="chrome://resources/js/cr/ui.js"></script>
- <script src="chrome://resources/js/util.js"></script>
- <script src="chrome://media-internals/media_internals.js"></script>
- <script src="chrome://media-internals/strings.js"></script>
- <title>Media Internals</title>
- </head>
- <body>
- <h2>Active media players:</h2>
- <ul id="media-players"></ul>
- <h2>Active audio streams:</h2>
- <div id="audio-streams"></div>
- <h2>Cached resources:</h2>
- <div id="cache-entries"></div>
- <script src="chrome://resources/js/i18n_template.js"></script>
- <script src="chrome://resources/js/i18n_process.js"></script>
- <script src="chrome://resources/js/jstemplate_compiled.js"></script>
- </body>
+<!DOCTYPE html>
+<html i18n-values="dir:textdirection">
+<head>
+ <meta charset="utf-8">
+ <title i18n-content="Media Internals"></title>
+ <link rel="stylesheet" href="media_internals.css">
+ <script src="chrome://resources/js/cr.js"></script>
+</head>
+
+<body>
+ <textarea id="clipboard-textarea" class="hidden"></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>
+ </div>
+ <div id="property-wrapper">
+ <h2>Properties <button id="copy-button">copy to clipboard</button> </h2>
+ <table id="property-table">
+ <thead>
+ <tr>
+ <td>Property Name</td> <td>Value</td>
+ </tr>
+ </thead>
+ </table>
+ <ul id="graphs"></ul>
+ </div>
+ <div id="log-wrapper">
+ <h2>
+ Log <input id="filter-text" type="text">
+ </h2>
+ <table id="log">
+ <thead>
+ <tr>
+ <td>Timestamp</td>
+ <td>Property</td>
+ <td>Value</td>
+ </tr>
+ </thead>
+ <tbody></tbody>
+ </table>
+ </div>
+ </div>
+ <script src="chrome://media-internals/media_internals.js"></script>
+</body>
</html>
diff --git a/chromium/content/browser/resources/media/media_internals.js b/chromium/content/browser/resources/media/media_internals.js
index c3e3a1ed1d1..936f86d357b 100644
--- a/chromium/content/browser/resources/media/media_internals.js
+++ b/chromium/content/browser/resources/media/media_internals.js
@@ -1,281 +1,15 @@
-// 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.
+var media = {};
+
+<include src="main.js"/>
+<include src="util.js"/>
<include src="cache_entry.js"/>
<include src="disjoint_range_set.js"/>
-<include src="event_list.js"/>
-<include src="item_store.js"/>
-<include src="media_player.js"/>
-<include src="metrics.js"/>
-<include src="util.js"/>
-
-cr.define('media', function() {
- 'use strict';
-
- // Stores information on open audio streams, referenced by id.
- var audioStreams = new media.ItemStore;
-
- // Active media players, indexed by 'render_id:player_id'.
- var mediaPlayers = {};
-
- // Cached files indexed by key and source id.
- var cacheEntriesByKey = {};
- var cacheEntries = {};
-
- // Map of event source -> url.
- var requestURLs = {};
-
- // Constants passed to us from Chrome.
- var eventTypes = {};
- var eventPhases = {};
-
- // The <div>s on the page in which to display information.
- var audioStreamDiv;
- var cacheDiv;
-
- // A timer used to limit the rate of redrawing the Media Players section.
- var redrawTimer = null;
-
- /**
- * Initialize variables and ask MediaInternals for all its data.
- */
- function initialize() {
- audioStreamDiv = $('audio-streams');
- cacheDiv = $('cache-entries');
-
- // Get information about all currently active media.
- chrome.send('getEverything');
- }
-
- /**
- * Write the set of audio streams to the DOM.
- */
- function printAudioStreams() {
-
- /**
- * Render a single stream as a <li>.
- * @param {Object} stream The stream to render.
- * @return {HTMLElement} A <li> containing the stream information.
- */
- function printStream(stream) {
- var out = document.createElement('li');
- out.id = stream.id;
- out.className = 'audio-stream';
- out.setAttribute('status', stream.status);
-
- out.textContent += 'Audio stream ' + stream.id.split('.')[1];
- out.textContent += ' is ' + (stream.playing ? 'playing' : 'paused');
- if (typeof stream.volume != 'undefined') {
- out.textContent += ' at ' + (stream.volume * 100).toFixed(0);
- out.textContent += '% volume.';
- }
- return out;
- }
-
- var out = document.createElement('ul');
- audioStreams.map(printStream).forEach(function(s) {
- out.appendChild(s);
- });
-
- audioStreamDiv.textContent = '';
- audioStreamDiv.appendChild(out);
- }
-
- /**
- * Redraw each MediaPlayer.
- */
- function printMediaPlayers() {
- for (var key in mediaPlayers) {
- mediaPlayers[key].redraw();
- }
- redrawTimer = null;
- }
-
- /**
- * Write the set of sparse CacheEntries to the DOM.
- */
- function printSparseCacheEntries() {
- var out = document.createElement('ul');
- for (var key in cacheEntriesByKey) {
- if (cacheEntriesByKey[key].sparse)
- out.appendChild(cacheEntriesByKey[key].toListItem());
- }
-
- cacheDiv.textContent = '';
- cacheDiv.appendChild(out);
- }
-
- /**
- * Receiving data for an audio stream.
- * Add it to audioStreams and update the page.
- * @param {Object} stream JSON representation of an audio stream.
- */
- function addAudioStream(stream) {
- audioStreams.addItem(stream);
- printAudioStreams();
- }
-
- /**
- * Receiving all data.
- * Add it all to the appropriate stores and update the page.
- * @param {Object} stuff JSON containing lists of data.
- * @param {Object} stuff.audio_streams A dictionary of audio streams.
- */
- function onReceiveEverything(stuff) {
- audioStreams.addItems(stuff.audio_streams);
- printAudioStreams();
- }
-
- /**
- * Removing an item from the appropriate store.
- * @param {string} id The id of the item to be removed, in the format
- * "item_type.identifying_info".
- */
- function onItemDeleted(id) {
- var type = id.split('.')[0];
- switch (type) {
- case 'audio_streams':
- audioStreams.removeItem(id);
- printAudioStreams();
- break;
- }
- }
-
- /**
- * A render process has ended, delete any media players associated with it.
- * @param {number} renderer The id of the render process.
- */
- function onRendererTerminated(renderer) {
- for (var key in mediaPlayers) {
- if (mediaPlayers[key].renderer == renderer) {
- $('media-players').removeChild(mediaPlayers[key]);
- delete mediaPlayers[key];
- break;
- }
- }
- printMediaPlayers();
- }
-
- /**
- * Receiving net events.
- * Update cache information and update that section of the page.
- * @param {Array} updates A list of net events that have occurred.
- */
- function onNetUpdate(updates) {
- updates.forEach(function(update) {
- var id = update.source.id;
- if (!cacheEntries[id])
- cacheEntries[id] = new media.CacheEntry;
-
- switch (eventPhases[update.phase] + '.' + eventTypes[update.type]) {
- case 'PHASE_BEGIN.DISK_CACHE_ENTRY_IMPL':
- var key = update.params.key;
-
- // Merge this source with anything we already know about this key.
- if (cacheEntriesByKey[key]) {
- cacheEntriesByKey[key].merge(cacheEntries[id]);
- cacheEntries[id] = cacheEntriesByKey[key];
- } else {
- cacheEntriesByKey[key] = cacheEntries[id];
- }
- cacheEntriesByKey[key].key = key;
- break;
-
- case 'PHASE_BEGIN.SPARSE_READ':
- cacheEntries[id].readBytes(update.params.offset,
- update.params.buff_len);
- cacheEntries[id].sparse = true;
- break;
-
- case 'PHASE_BEGIN.SPARSE_WRITE':
- cacheEntries[id].writeBytes(update.params.offset,
- update.params.buff_len);
- cacheEntries[id].sparse = true;
- break;
-
- case 'PHASE_BEGIN.URL_REQUEST_START_JOB':
- requestURLs[update.source.id] = update.params.url;
- break;
-
- case 'PHASE_NONE.HTTP_TRANSACTION_READ_RESPONSE_HEADERS':
- // Record the total size of the file if this was a range request.
- var range = /content-range:\s*bytes\s*\d+-\d+\/(\d+)/i.exec(
- update.params.headers);
- var key = requestURLs[update.source.id];
- delete requestURLs[update.source.id];
- if (range && key) {
- if (!cacheEntriesByKey[key]) {
- cacheEntriesByKey[key] = new media.CacheEntry;
- cacheEntriesByKey[key].key = key;
- }
- cacheEntriesByKey[key].size = range[1];
- }
- break;
- }
- });
-
- printSparseCacheEntries();
- }
-
- /**
- * Receiving values for constants. Store them for later use.
- * @param {Object} constants A dictionary of constants.
- * @param {Object} constants.eventTypes A dictionary of event name -> int.
- * @param {Object} constants.eventPhases A dictionary of event phase -> int.
- */
- function onReceiveConstants(constants) {
- var events = constants.eventTypes;
- for (var e in events) {
- eventTypes[events[e]] = e;
- }
-
- var phases = constants.eventPhases;
- for (var p in phases) {
- eventPhases[phases[p]] = p;
- }
- }
-
- /**
- * Receiving notification of a media event.
- * @param {Object} event The json representation of a MediaLogEvent.
- */
- function onMediaEvent(event) {
- var source = event.renderer + ':' + event.player;
- var item = mediaPlayers[source] ||
- new media.MediaPlayer({id: source, renderer: event.renderer});
- mediaPlayers[source] = item;
- item.addEvent(event);
-
- // Both media and net events could provide the size of the file.
- // Media takes priority, but keep the size in both places synchronized.
- if (cacheEntriesByKey[item.properties.url]) {
- item.properties.total_bytes = item.properties.total_bytes ||
- cacheEntriesByKey[item.properties.url].size;
- cacheEntriesByKey[item.properties.url].size = item.properties.total_bytes;
- }
-
- // Events tend to arrive in groups; don't redraw the page too often.
- if (!redrawTimer)
- redrawTimer = setTimeout(printMediaPlayers, 50);
- }
-
- return {
- initialize: initialize,
- addAudioStream: addAudioStream,
- cacheEntriesByKey: cacheEntriesByKey,
- onReceiveEverything: onReceiveEverything,
- onItemDeleted: onItemDeleted,
- onRendererTerminated: onRendererTerminated,
- onNetUpdate: onNetUpdate,
- onReceiveConstants: onReceiveConstants,
- onMediaEvent: onMediaEvent
- };
-});
+<include src="player_info.js"/>
+<include src="manager.js"/>
+<include src="client_renderer.js"/>
-/**
- * Initialize everything once we have access to the DOM.
- */
-document.addEventListener('DOMContentLoaded', function() {
- media.initialize();
-});
+media.initialize(new Manager(new ClientRenderer()));
diff --git a/chromium/content/browser/resources/media/media_player.js b/chromium/content/browser/resources/media/media_player.js
deleted file mode 100644
index a9d5d6b3333..00000000000
--- a/chromium/content/browser/resources/media/media_player.js
+++ /dev/null
@@ -1,154 +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.
-
-cr.define('media', function() {
- 'use strict';
-
- /**
- * This class inherits from <li> and is designed to store and display
- * information about an open media player.
- */
- var MediaPlayer = cr.ui.define('li');
-
- MediaPlayer.prototype = {
- __proto__: HTMLLIElement.prototype,
- renderer: null,
- id: null,
-
- /**
- * Decorate this <li> as a MediaPlayer.
- */
- decorate: function() {
- this.properties = {};
-
- this.url_ = document.createElement('span');
- this.url_.textContent = 'URL Unknown';
-
- this.summary_ = document.createElement('summary');
- this.summary_.appendChild(this.url_);
-
- var bufferedDiv = document.createElement('div');
- bufferedDiv.className = 'buffered';
- this.summary_.appendChild(bufferedDiv);
-
- // Create our canvii.
- function createCanvas(label) {
- var canvas = document.createElement('canvas');
- canvas.width = media.BAR_WIDTH;
- canvas.height = media.BAR_HEIGHT;
- return canvas;
- }
- this.bufferedCanvas_ = createCanvas();
- this.cacheReadsCanvas_ = createCanvas();
- this.cacheWritesCanvas_ = createCanvas();
-
- // Create our per-canvas entry divs that are initially hidden.
- function addEntry(label, canvas) {
- var labelDiv = document.createElement('div');
- labelDiv.textContent = label;
- var canvasDiv = document.createElement('div');
- canvasDiv.appendChild(canvas);
- var entryDiv = document.createElement('div');
- entryDiv.appendChild(labelDiv);
- entryDiv.appendChild(canvasDiv);
- entryDiv.hidden = true;
- bufferedDiv.appendChild(entryDiv);
- return entryDiv;
- }
- this.bufferedEntry_ = addEntry('Buffered', this.bufferedCanvas_);
- this.cacheReadsEntry_ = addEntry('Cache Reads', this.cacheReadsCanvas_);
- this.cacheWritesEntry_ = addEntry(
- 'Cache Writes', this.cacheWritesCanvas_);
-
- this.details_ = document.createElement('details');
- this.details_.appendChild(this.summary_);
-
- this.propertyTable_ = document.createElement('table');
- this.events_ = new media.EventList;
- this.metrics_ = new media.Metrics;
-
- var properties = media.createDetailsLi();
- properties.summary.textContent = 'Properties:';
- properties.details.appendChild(this.propertyTable_);
-
- var ul = document.createElement('ul');
- ul.appendChild(properties);
- ul.appendChild(this.metrics_);
- ul.appendChild(this.events_);
- this.details_.appendChild(ul);
-
- this.appendChild(this.details_);
- $('media-players').appendChild(this);
- },
-
- /**
- * Record an event and update statistics etc.
- * @param {Object} event The event that occurred.
- */
- addEvent: function(event) {
- for (var key in event.params) {
- this.properties[key] = event.params[key];
- }
-
- if (event.type == 'LOAD' && event.params['url']) {
- this.url_.textContent = event.params['url'];
- }
-
- if (event.type == 'BUFFERED_EXTENTS_CHANGED') {
- return;
- }
- this.events_.addEvent(event);
- this.metrics_.addEvent(event);
- },
-
- /**
- * Update the summary line and properties table and redraw the canvas.
- * @return {HTMLElement} A <li> representing this MediaPlayer.
- */
- redraw: function() {
- media.appendDictionaryToTable(this.properties, this.propertyTable_);
-
- this.setAttribute('status', this.properties.state);
-
- // Don't bother drawing anything if we don't know the total size.
- var size = this.properties.total_bytes;
- if (!size) {
- return;
- }
-
- // Draw the state of BufferedResourceLoader.
- this.bufferedEntry_.hidden = false;
- var canvas = this.bufferedCanvas_;
- var context = canvas.getContext('2d');
- context.fillStyle = '#aaa';
- context.fillRect(0, 0, canvas.width, canvas.height);
-
- var left = this.properties.buffer_start / size * canvas.width;
- var middle = this.properties.buffer_current / size * canvas.width;
- var right = this.properties.buffer_end / size * canvas.width;
- context.fillStyle = '#a0a';
- context.fillRect(left, 0, middle - left, canvas.height);
- context.fillStyle = '#aa0';
- context.fillRect(middle, 0, right - middle, canvas.height);
-
- // Only show cached file information if we have something.
- var cacheEntry = media.cacheEntriesByKey[this.properties.url];
- if (!cacheEntry) {
- return;
- }
-
- // Draw cache reads.
- this.cacheReadsEntry_.hidden = false;
- cacheEntry.drawCacheReadsToCanvas(this.cacheReadsCanvas_);
-
- // Draw cache writes.
- this.cacheWritesEntry_.hidden = false;
- cacheEntry.drawCacheWritesToCanvas(this.cacheWritesCanvas_);
- },
- };
-
- return {
- MediaPlayer: MediaPlayer
- };
-});
diff --git a/chromium/content/browser/resources/media/metrics.js b/chromium/content/browser/resources/media/metrics.js
deleted file mode 100644
index c812d44f56c..00000000000
--- a/chromium/content/browser/resources/media/metrics.js
+++ /dev/null
@@ -1,116 +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.
-
-cr.define('media', function() {
- 'use strict';
-
- // A set of parameter names. An entry of 'abc' allows metrics to specify
- // events with specific values of 'abc'.
- var metricProperties = {
- 'pipeline_state': true,
- };
-
- // A set of metrics to measure. The user will see the most recent and average
- // measurement of the time between each metric's start and end events.
- var metrics = {
- 'seek': {
- 'start': 'SEEK',
- 'end': 'pipeline_state=started'
- },
- 'first frame': {
- 'start': 'WEBMEDIAPLAYER_CREATED',
- 'end': 'pipeline_state=started'
- },
- };
-
- /**
- * This class measures times between the events specified above. It inherits
- * <li> and contains a table that displays the measurements.
- */
- var Metrics = cr.ui.define('li');
-
- Metrics.prototype = {
- __proto__: HTMLLIElement.prototype,
-
- /**
- * Decorate this <li> as a Metrics.
- */
- decorate: function() {
- this.table_ = document.createElement('table');
- var details = document.createElement('details');
- var summary = media.makeElement('summary', 'Metrics:');
- details.appendChild(summary);
- details.appendChild(this.table_);
- this.appendChild(details);
-
- var hRow = document.createElement('tr');
- hRow.appendChild(media.makeElement('th', 'Metric:'));
- hRow.appendChild(media.makeElement('th', 'Last Measure:'));
- hRow.appendChild(media.makeElement('th', 'Average:'));
- var header = document.createElement('thead');
- header.appendChild(hRow);
- this.table_.appendChild(header);
-
- for (var metric in metrics) {
- var last = document.createElement('td');
- var avg = document.createElement('td');
- this[metric] = {
- count: 0,
- total: 0,
- start: null,
- last: last,
- avg: avg
- };
- var row = document.createElement('tr');
- row.appendChild(media.makeElement('td', metric + ':'));
- row.appendChild(last);
- row.appendChild(avg);
- this.table_.appendChild(row);
- }
- },
-
- /**
- * An event has occurred. Update any metrics that refer to this type
- * of event. Can be called multiple times by addEvent below if the metrics
- * refer to specific parameters.
- * @param {Object} event The MediaLogEvent that has occurred.
- * @param {string} type The type of event.
- */
- addEventInternal: function(event, type) {
- for (var metric in metrics) {
- var m = this[metric];
- if (type == metrics[metric].start && !m.start) {
- m.start = event.ticksMillis;
- } else if (type == metrics[metric].end && m.start != null) {
- var last = event.ticksMillis - m.start;
- m.last.textContent = last.toFixed(1);
- m.total += last;
- m.count++;
- if (m.count > 1)
- m.avg.textContent = (m.total / m.count).toFixed(1);
- m.start = null;
- }
- }
- },
-
- /**
- * An event has occurred. Update any metrics that refer to events of this
- * type or with this event's parameters.
- * @param {Object} event The MediaLogEvent that has occurred.
- */
- addEvent: function(event) {
- this.addEventInternal(event, event.type);
- for (var p in event.params) {
- if (p in metricProperties) {
- var type = p + '=' + event.params[p];
- this.addEventInternal(event, type);
- }
- }
- },
- };
-
- return {
- Metrics: Metrics,
- };
-});
diff --git a/chromium/content/browser/resources/media/new/integration_test.html b/chromium/content/browser/resources/media/new/integration_test.html
deleted file mode 100644
index 3a5225cb647..00000000000
--- a/chromium/content/browser/resources/media/new/integration_test.html
+++ /dev/null
@@ -1,86 +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.
--->
-<!DOCTYPE html>
-<html>
- <head>
- <script src="webui_resource_test.js"></script>
- <script src="util.js"></script>
- <script src="player_manager.js"></script>
- <script src="player_info.js"></script>
- <script src="main.js"></script>
- </head>
- <body>
- <script>
- window.setUp = function() {
- var doNothing = function() {};
- var mockRenderer = {
- redrawList: doNothing,
- update: doNothing,
- select: doNothing
- };
-
- var manager = new PlayerManager(mockRenderer);
- media.initialize(manager);
-
- window.playerManager = manager;
- };
-
- // The renderer and player ids are completely arbitrarily.
- var TEST_RENDERER = 12;
- var TEST_PLAYER = 4;
- var TEST_NAME = TEST_RENDERER + ':' + TEST_PLAYER;
-
- // Correctly use the information from a media event.
- window.testOnMediaEvent = function() {
- var event = {
- ticksMillis: 132,
- renderer: TEST_RENDERER,
- player: TEST_PLAYER,
- params: {
- fps: 60,
- other: 'hi'
- }
- };
-
- window.media.onMediaEvent(event);
- var info = window.playerManager.players_[TEST_NAME];
-
- assertEquals(event.ticksMillis, info.firstTimestamp_);
- assertEquals(TEST_NAME, info.id);
- assertEquals(event.params.fps, info.properties.fps);
- };
-
- // Remove a player.
- window.testOnRenderTerminated = function() {
- window.testOnMediaEvent();
-
- window.playerManager.shouldRemovePlayer_ = function() {
- return true;
- };
-
- window.media.onRendererTerminated(TEST_RENDERER);
- assertEquals(undefined, window.playerManager.players_[TEST_NAME]);
- };
-
- // Audio Streams are weird, they are handled separately
- window.testAddAudioStream = function() {
- var event = {
- id: 'ID',
- status: 'created',
- playing: true
- };
-
- window.media.addAudioStream(event);
-
- var player = window.playerManager.players_[event.id];
- assertTrue(undefined !== player);
- assertEquals(event.playing, player.properties['playing']);
- };
-
- runTests();
- </script>
- </body>
-</html>
diff --git a/chromium/content/browser/resources/media/new/main.js b/chromium/content/browser/resources/media/new/main.js
deleted file mode 100644
index 61f6407bcf5..00000000000
--- a/chromium/content/browser/resources/media/new/main.js
+++ /dev/null
@@ -1,134 +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.
-
-/**
- * A global object that gets used by the C++ interface.
- */
-var media = (function() {
- 'use strict';
-
- var manager = null;
-
- /**
- * Users of |media| must call initialize prior to calling other methods.
- */
- function initialize(playerManager) {
- manager = playerManager;
- }
-
- /**
- * Call to modify or add a system property.
- */
- function onSystemProperty(timestamp, key, value) {
- console.log('System properties not yet implemented');
- }
-
- /**
- * Call to modify or add a property on a player.
- */
- function onPlayerProperty(id, timestamp, key, value) {
- manager.updatePlayerInfo(id, timestamp, key, value);
- }
-
- function onPlayerPropertyNoRecord(id, timestamp, key, value) {
- manager.updatePlayerInfoNoRecord(id, timestamp, key, value);
- }
-
- /**
- * Call to add a player.
- */
- function onPlayerOpen(id, timestamp) {
- manager.addPlayer(id, timestamp);
- }
-
- /**
- * Call to remove a player.
- */
- function onPlayerClose(id) {
- manager.removePlayer(id);
- }
-
- var media = {
- onSystemProperty: onSystemProperty,
- onPlayerProperty: onPlayerProperty,
- onPlayerPropertyNoRecord: onPlayerPropertyNoRecord,
- onPlayerOpen: onPlayerOpen,
- onPlayerClose: onPlayerClose,
-
- initialize: initialize
- };
-
- // Everything beyond this point is for backwards compatibility reasons.
- // It will go away when the backend is updated.
-
- media.onNetUpdate = function(update) {
- // TODO(tyoverby): Implement
- };
-
- media.onRendererTerminated = function(renderId) {
- util.object.forEach(manager.players_, function(playerInfo, id) {
- if (playerInfo.properties['render_id'] == renderId) {
- media.onPlayerClose(id);
- }
- });
- };
-
- // For whatever reason, addAudioStream is also called on
- // the removal of audio streams.
- media.addAudioStream = function(event) {
- switch (event.status) {
- case 'created':
- media.onPlayerOpen(event.id);
- // We have to simulate the timestamp since it isn't provided to us.
- media.onPlayerProperty(
- event.id, (new Date()).getTime(), 'playing', event.playing);
- break;
- case 'closed':
- media.onPlayerClose(event.id);
- break;
- }
- };
- 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.onMediaEvent = function(event) {
- var source = event.renderer + ':' + event.player;
-
- // Although this gets called on every event, there is nothing we can do
- // about this because there is no onOpen event.
- media.onPlayerOpen(source);
- media.onPlayerPropertyNoRecord(
- source, event.ticksMillis, 'render_id', event.renderer);
- media.onPlayerPropertyNoRecord(
- source, event.ticksMillis, 'player_id', event.player);
-
- var propertyCount = 0;
- util.object.forEach(event.params, function(value, key) {
- key = key.trim();
-
- // These keys get spammed *a lot*, so put them on the display
- // but don't log list.
- if (key === 'buffer_start' ||
- key === 'buffer_end' ||
- key === 'buffer_current' ||
- key === 'is_downloading_data') {
- media.onPlayerPropertyNoRecord(
- source, event.ticksMillis, key, value);
- } else {
- media.onPlayerProperty(source, event.ticksMillis, key, value);
- }
- propertyCount += 1;
- });
-
- if (propertyCount === 0) {
- media.onPlayerProperty(
- source, event.ticksMillis, 'EVENT', event.type);
- }
- };
-
- return media;
-}());
diff --git a/chromium/content/browser/resources/media/new/media_internals.html b/chromium/content/browser/resources/media/new/media_internals.html
deleted file mode 100644
index 0e95353aeef..00000000000
--- a/chromium/content/browser/resources/media/new/media_internals.html
+++ /dev/null
@@ -1,18 +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.
--->
-<!DOCTYPE html>
-<html i18n-values="dir:textdirection">
-<head>
- <meta charset="utf-8">
- <title i18n-content="Media Internals"></title>
-
- <script src="chrome://media-internals/media_internals.js"></script>
-</head>
-
-<body>
- Hello World
-</body>
-</html>
diff --git a/chromium/content/browser/resources/media/new/media_internals.js b/chromium/content/browser/resources/media/new/media_internals.js
deleted file mode 100644
index 103ef74fbc0..00000000000
--- a/chromium/content/browser/resources/media/new/media_internals.js
+++ /dev/null
@@ -1,18 +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.
-
-var media = {};
-
-var doNothing = function() {};
-
-// Silence the backend calls.
-media.initialize = doNothing;
-media.addAudioStream = doNothing;
-media.cacheEntriesByKey = doNothing;
-media.onReceiveEverything = doNothing;
-media.onItemDeleted = doNothing;
-media.onRendererTerminated = doNothing;
-media.onNetUpdate = doNothing;
-media.onReceiveConstants = doNothing;
-media.onMediaEvent = doNothing;
diff --git a/chromium/content/browser/resources/media/new/player_info_test.html b/chromium/content/browser/resources/media/new/player_info_test.html
deleted file mode 100644
index 46cc05ee3d9..00000000000
--- a/chromium/content/browser/resources/media/new/player_info_test.html
+++ /dev/null
@@ -1,146 +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.
--->
-<!DOCTYPE html>
-<html>
- <head>
- <script src="webui_resource_test.js"></script>
- <script src="player_manager.js"></script>
- <script src="player_info.js"></script>
- </head>
- <body>
- <script>
- window.setUp = function() {
- window.pi = new PlayerInfo('example_id');
- };
-
- window.tearDown = function() {
- window.pi = null;
- };
-
- // Test that an ID is set correctly.
- window.testConstructorStringID = function() {
- assertEquals('example_id', window.pi.id);
- };
-
- // Test that numerical IDs are valid.
- window.testConstructorNumberId = function() {
- var pi = new PlayerInfo(5);
- assertEquals(5, pi.id);
- };
-
- // Make sure that a new PlayerInfo has no events.
- window.testEmptyEvents = function() {
- assertEquals(0, window.pi.allEvents.length);
- };
-
- // Check that the most recent property gets updated.
- window.testAddProperty = function() {
- var key = 'key',
- value = 'value',
- value2 = 'value2';
-
- window.pi.addProperty(0, key, value);
- assertEquals(value, window.pi.properties[key]);
-
- window.pi.addProperty(0, key, value2);
- assertEquals(value2, window.pi.properties[key]);
-
- };
-
- // Make sure that the first timestamp that gets sent
- // is recorded as the base timestamp.
- window.testFirstTimestamp = function() {
- var pi = new PlayerInfo('example_ID');
- var timestamp = 5000;
- pi.addProperty(timestamp, 'key', 'value');
-
- assertEquals(timestamp, pi.firstTimestamp_);
- };
-
- // Adding a property with a non-string key should
- // throw an exception.
- window.testWrongKeyType = function() {
- var pi = new PlayerInfo('example_ID');
- assertThrows(function() {
- pi.addProperty(0, 5, 'some value');
- });
- };
-
- // Subsequent events should have their log offset based
- // on the first timestamp added.
- window.testAddPropertyTimestampOffset = function() {
- var firstTimestamp = 500,
- secondTimestamp = 550,
- deltaT = secondTimestamp - firstTimestamp,
- key = 'key',
- value = 'value';
-
- var pi = new PlayerInfo('example_ID');
- pi.addProperty(firstTimestamp, key, value);
- pi.addProperty(secondTimestamp, key, value);
-
- assertEquals(firstTimestamp, pi.firstTimestamp_);
- assertEquals(0, pi.allEvents[0].time);
- assertEquals(deltaT, pi.allEvents[1].time);
-
- assertTrue(undefined !== pi.pastValues[key]);
-
- console.log(pi.pastValues);
-
- assertEquals(0, pi.pastValues[key][0].time);
- assertEquals(deltaT, pi.pastValues[key][1].time);
- };
-
- // Check to make sure that properties are correctly
- // added to the relevant pastValues array.
- window.testAddPropertyPastValues = function() {
- var pi = new PlayerInfo('example_ID'),
- timestamp = 50,
- key = 'key',
- value = 'value';
-
- pi.addProperty(timestamp, key, value);
-
- assertEquals(value, pi.pastValues[key][0].value);
- assertEquals(key, pi.pastValues[key][0].key);
- assertEquals(0, pi.pastValues[key][0].time);
- };
-
- // The list of all events should be recorded in correctly.
- window.testAllEvents = function() {
- var pi = new PlayerInfo('example_ID'),
- timestamp = 50,
- key = 'key',
- value = 'value',
- key2 = 'key2',
- value2 = 'value2';
-
- pi.addProperty(timestamp, key, value);
- assertEquals(value, pi.allEvents[0].value);
- assertEquals(key, pi.allEvents[0].key);
-
- pi.addProperty(timestamp, key2, value2);
- assertEquals(value2, pi.allEvents[1].value);
- assertEquals(key2, pi.allEvents[1].key);
- };
-
- // Using noRecord should make it not show up in allEvents,
- // but it should still show up in pastValues[key].
- window.testNoRecord = function() {
- var pi = new PlayerInfo('example_ID'),
- timestamp = 50,
- key = 'key',
- value = 'value';
- pi.addPropertyNoRecord(timestamp, key, value);
-
- assertEquals(value, pi.properties[key]);
- assertEquals(0, pi.allEvents.length);
- assertEquals(1, pi.pastValues[key].length);
- };
- runTests();
- </script>
- </body>
-</html>
diff --git a/chromium/content/browser/resources/media/new/player_manager.js b/chromium/content/browser/resources/media/new/player_manager.js
deleted file mode 100644
index 3de93357f98..00000000000
--- a/chromium/content/browser/resources/media/new/player_manager.js
+++ /dev/null
@@ -1,111 +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.
-
-/**
- * @fileoverview Keeps track of all the existing
- * PlayerProperty objects and is the entry-point for messages from the backend.
- */
-var PlayerManager = (function() {
- 'use strict';
-
- function PlayerManager(renderManager) {
- this.players_ = {};
- this.renderman_ = renderManager;
- renderManager.playerManager = this;
-
- this.shouldRemovePlayer_ = function() {
- // This is only temporary until we get the UI hooked up.
- return true;
- };
- }
-
- PlayerManager.prototype = {
-
- /**
- * Adds a player to the list of players to manage.
- */
- addPlayer: function(id) {
- if (this.players_[id]) {
- return;
- }
- // Make the PlayerProperty and add it to the mapping
- this.players_[id] = new PlayerInfo(id);
-
- this.renderman_.redrawList();
- },
-
- /**
- * Attempts to remove a player from the UI.
- * @param id The ID of the player to remove.
- */
- removePlayer: function(id) {
- // Look at the check box to see if we should actually
- // remove it from the UI
- if (this.shouldRemovePlayer_()) {
- delete this.players_[id];
- this.renderman_.redrawList();
- } else if (this.players_[id]) {
- // Set a property on it to be removed at a later time
- this.players_[id].toRemove = true;
- }
- },
-
- /**
- * Selects a player and displays it on the UI.
- * This method is called from the UI.
- * @param id The ID of the player to display.
- */
- selectPlayer: function(id) {
- if (!this.players_[id]) {
- throw new Error('[selectPlayer] Id ' + id + ' does not exist.');
- }
-
- this.renderman_.select(id);
- },
-
- updatePlayerInfoNoRecord: function(id, timestamp, key, value) {
- if (!this.players_[id]) {
- console.error('[updatePlayerInfo] Id ' + id +
- ' does not exist');
- return;
- }
-
- this.players_[id].addPropertyNoRecord(timestamp, key, value);
-
- // If we can potentially rename the player, do so.
- if (key === 'name' || key === 'url') {
- this.renderman_.redrawList();
- }
-
- this.renderman_.update();
- },
-
- /**
- *
- * @param id The unique ID that identifies the player to be updated.
- * @param timestamp The timestamp of when the change occured. This
- * timestamp is *not* normalized.
- * @param key The name of the property to be added/changed.
- * @param value The value of the property.
- */
- updatePlayerInfo: function(id, timestamp, key, value) {
- if (!this.players_[id]) {
- console.error('[updatePlayerInfo] Id ' + id +
- ' does not exist');
- return;
- }
-
- this.players_[id].addProperty(timestamp, key, value);
-
- // If we can potentially rename the player, do so.
- if (key === 'name' || key === 'url') {
- this.renderman_.redrawList();
- }
-
- this.renderman_.update();
- }
- };
-
- return PlayerManager;
-}());
diff --git a/chromium/content/browser/resources/media/new/player_manager_test.html b/chromium/content/browser/resources/media/new/player_manager_test.html
deleted file mode 100644
index eff78b53c59..00000000000
--- a/chromium/content/browser/resources/media/new/player_manager_test.html
+++ /dev/null
@@ -1,155 +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.
--->
-<!DOCTYPE html>
-<html>
- <head>
- <script src="webui_resource_test.js"></script>
- <script src="player_manager.js"></script>
- <script src="player_info.js"></script>
- </head>
- <body>
- <script>
- var doNothing = function() {
- };
-
- var emptyRenderMan = {
- redrawList: doNothing,
- update: doNothing,
- select: doNothing
- };
-
- window.setUp = function() {
- window.pm = new PlayerManager(emptyRenderMan);
- };
-
- window.tearDown = function() {
- window.pm = null;
- };
-
- // Test a normal case of .addPlayer
- window.testAddPlayer = function() {
- window.pm.addPlayer('someid');
- assertTrue(undefined !== window.pm.players_['someid']);
- };
-
- // Make sure that adding a player forces a redraw
- // on the renderManager.
- window.testAddPlayerForceRedraw = function() {
- var redrew = false;
- var mockRenderManager = {
- redrawList: function() {
- redrew = true;
- }
- };
- var pm = new PlayerManager(mockRenderManager);
-
- pm.addPlayer('someid');
- assertTrue(redrew);
- };
-
- // On occasion, the backend will add an existing ID multiple times.
- // make sure this doesn't break anything.
- window.testAddPlayerAlreadyExisting = function() {
- window.pm.addPlayer('someid');
- window.pm.addPlayer('someid');
- assertTrue(undefined !== window.pm.players_['someid']);
- };
-
- // If the removal is set, make sure that a player
- // gets removed from the PlayerManager.
- window.testRemovePlayerShouldRemove = function() {
- // Because we don't have the checkbox.
- window.pm.shouldRemovePlayer_ = function() {
- return true;
- };
- window.pm.addPlayer('someid');
- assertTrue(undefined !== window.pm.players_['someid']);
- window.pm.removePlayer('someid');
- assertTrue(undefined === window.pm.players_['someid']);
- };
-
- // On the removal of a player, the renderer should be forced
- // to redraw the list.
- window.testRemovePlayerRedraw = function() {
- var redrew = false;
-
- var fakeObj = {
- redrawList: function() {
- redrew = true;
- }
- };
-
- var pm = new PlayerManager(fakeObj);
- // Because we don't have the checkbox;
- pm.shouldRemovePlayer_ = function() {
- return true;
- };
-
-
- pm.addPlayer('someid');
- assertTrue(undefined !== pm.players_['someid']);
- pm.removePlayer('someid');
- assertTrue(undefined === pm.players_['someid']);
-
- assertTrue(redrew);
- };
-
- // If you shouldn't remove the player, the player shouldn't be
- // removed.
- window.testRemovePlayerNoRemove = function() {
- window.pm = new PlayerManager(emptyRenderMan);
- // Because we don't have the checkbox;
- window.pm.shouldRemovePlayer_ = function() {
- return false;
- };
- window.pm.addPlayer('someid');
- assertTrue(undefined !== window.pm.players_['someid']);
- window.pm.removePlayer('someid');
- assertTrue(undefined !== window.pm.players_['someid']);
- };
-
-
- // Removing a nonexistant player shouldn't break anything
- // The backend also occasionally does this.
- window.testRemovePlayerNonExistant = function() {
- // Because we don't have the checkbox;
- window.pm.shouldRemovePlayer_ = function() {
- return false;
- };
- window.pm.removePlayer('someid');
- assertTrue(undefined === window.pm.players_['someid']);
- };
-
- // Trying to select a non-existant player should throw
- // an exception
- window.testSelectNonExistant = function() {
- assertThrows(function() {
- window.pm.selectPlayer('someId');
- });
- };
-
- // Selecting an existing player should trigger a redraw
- window.testSelectExistingPlayer = function() {
- var selected = false;
- var redrew = false;
- var pm = new PlayerManager({
- select: function() {
- selected = true;
- },
- redrawList: function() {
- redrew = true;
- }
- });
- pm.addPlayer('someId');
- pm.selectPlayer('someId');
-
- assertTrue(selected);
- assertTrue(redrew);
- };
- runTests();
- </script>
- </body>
-</html>
diff --git a/chromium/content/browser/resources/media/new/util.js b/chromium/content/browser/resources/media/new/util.js
deleted file mode 100644
index 5909e9ee1eb..00000000000
--- a/chromium/content/browser/resources/media/new/util.js
+++ /dev/null
@@ -1,34 +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.
-
-/**
- * @fileoverview Some utility functions that don't belong anywhere else in the
- * code.
- */
-
-var util = (function() {
- var util = {};
- util.object = {};
- /**
- * Calls a function for each element in an object/map/hash.
- *
- * @param obj The object to iterate over.
- * @param f The function to call on every value in the object. F should have
- * the following arguments: f(value, key, object) where value is the value
- * of the property, key is the corresponding key, and obj is the object that
- * was passed in originally.
- * @param optObj The object use as 'this' within f.
- */
- util.object.forEach = function(obj, f, optObj) {
- 'use strict';
- var key;
- for (key in obj) {
- if (obj.hasOwnProperty(key)) {
- f.call(optObj, obj[key], key, obj);
- }
- }
- };
-
- return util;
-}());
diff --git a/chromium/content/browser/resources/media/new/webui_resource_test.js b/chromium/content/browser/resources/media/new/webui_resource_test.js
deleted file mode 100644
index 6b05a305a70..00000000000
--- a/chromium/content/browser/resources/media/new/webui_resource_test.js
+++ /dev/null
@@ -1,210 +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.
-
-/**
- * Tests that an observation matches the expected value.
- * @param {Object} expected The expected value.
- * @param {Object} observed The actual value.
- * @param {string=} opt_message Optional message to include with a test
- * failure.
- */
-function assertEquals(expected, observed, opt_message) {
- if (observed !== expected) {
- var message = 'Assertion Failed\n Observed: ' + observed +
- '\n Expected: ' + expected;
- if (opt_message)
- message = message + '\n ' + opt_message;
- throw new Error(message);
- }
-}
-
-/**
- * Verifies that a test result is true.
- * @param {boolean} observed The observed value.
- * @param {string=} opt_message Optional message to include with a test
- * failure.
- */
-function assertTrue(observed, opt_message) {
- assertEquals(true, observed, opt_message);
-}
-
-/**
- * Verifies that a test result is false.
- * @param {boolean} observed The observed value.
- * @param {string=} opt_message Optional message to include with a test
- * failure.
- */
-function assertFalse(observed, opt_message) {
- assertEquals(false, observed, opt_message);
-}
-
-/**
- * Verifies that the observed and reference values differ.
- * @param {Object} reference The target value for comparison.
- * @param {Object} observed The test result.
- * @param {string=} opt_message Optional message to include with a test
- * failure.
- */
-function assertNotEqual(reference, observed, opt_message) {
- if (observed === reference) {
- var message = 'Assertion Failed\n Observed: ' + observed +
- '\n Reference: ' + reference;
- if (opt_message)
- message = message + '\n ' + opt_message;
- throw new Error(message);
- }
-}
-
-/**
- * Verifies that a test evaluation results in an exception.
- * @param {!Function} f The test function.
- */
-function assertThrows(f) {
- var triggeredError = false;
- try {
- f();
- } catch (err) {
- triggeredError = true;
- }
- if (!triggeredError)
- throw new Error('Assertion Failed: throw expected.');
-}
-
-/**
- * Verifies that the contents of the expected and observed arrays match.
- * @param {!Array} expected The expected result.
- * @param {!Array} observed The actual result.
- */
-function assertArrayEquals(expected, observed) {
- var v1 = Array.prototype.slice.call(expected);
- var v2 = Array.prototype.slice.call(observed);
- var equal = v1.length == v2.length;
- if (equal) {
- for (var i = 0; i < v1.length; i++) {
- if (v1[i] !== v2[i]) {
- equal = false;
- break;
- }
- }
- }
- if (!equal) {
- var message =
- ['Assertion Failed', 'Observed: ' + v2, 'Expected: ' + v1].join('\n ');
- throw new Error(message);
- }
-}
-
-/**
- * Verifies that the expected and observed result have the same content.
- * @param {*} expected The expected result.
- * @param {*} observed The actual result.
- */
-function assertDeepEquals(expected, observed, opt_message) {
- if (typeof expected == 'object' && expected != null) {
- assertNotEqual(null, observed);
- for (var key in expected) {
- assertTrue(key in observed, opt_message);
- assertDeepEquals(expected[key], observed[key], opt_message);
- }
- for (var key in observed) {
- assertTrue(key in expected, opt_message);
- }
- } else {
- assertEquals(expected, observed, opt_message);
- }
-}
-
-/**
- * Defines runTests.
- */
-(function(exports) {
- /**
- * List of test cases.
- * @type {Array.<string>} List of function names for tests to run.
- */
- var testCases = [];
-
- /**
- * Indicates if all tests have run successfully.
- * @type {boolean}
- */
- var cleanTestRun = true;
-
- /**
- * Armed during setup of a test to call the matching tear down code.
- * @type {Function}
- */
- var pendingTearDown = null;
-
- /**
- * Runs all functions starting with test and reports success or
- * failure of the test suite.
- */
- function runTests() {
- for (var name in window) {
- if (typeof window[name] == 'function' && /^test/.test(name))
- testCases.push(name);
- }
- if (!testCases.length) {
- console.error('Failed to find test cases.');
- cleanTestRun = false;
- }
- continueTesting();
- }
-
- function reportPass(name) {
- 'use strict';
- var text = document.createTextNode(name + ': PASSED');
- var span = document.createElement('span');
- span.appendChild(text);
- document.body.appendChild(span);
- document.body.appendChild(document.createElement('br'));
- }
-
- function reportFail(name) {
- 'use strict';
- var text = document.createTextNode(name + ': =========FAILED=======');
- var span = document.createElement('span');
- span.appendChild(text);
- document.body.appendChild(span);
- document.body.appendChild(document.createElement('br'));
- }
-
- /**
- * Runs the next test in the queue. Reports the test results if the queue is
- * empty.
- */
- function continueTesting() {
- if (pendingTearDown) {
- pendingTearDown();
- pendingTearDown = null;
- }
- if (testCases.length > 0) {
- var fn = testCases.pop();
- var isAsyncTest = window[fn].length;
- try {
- if (window.setUp)
- window.setUp();
- pendingTearDown = window.tearDown;
- window[fn](continueTesting);
- reportPass(fn);
- } catch (err) {
- reportFail(fn);
- console.error('Failure in test ' + fn + '\n' + err);
- console.log(err.stack);
- cleanTestRun = false;
- }
- // Asynchronous tests must manually call continueTesting when complete.
- if (!isAsyncTest)
- continueTesting();
- }
- if (testCases.length) {
- domAutomationController.setAutomationId(1);
- domAutomationController.send('PENDING');
- }
- };
-
- exports.runTests = runTests;
-})(this);
-
diff --git a/chromium/content/browser/resources/media/new/player_info.js b/chromium/content/browser/resources/media/player_info.js
index af1f1944518..af1f1944518 100644
--- a/chromium/content/browser/resources/media/new/player_info.js
+++ b/chromium/content/browser/resources/media/player_info.js
diff --git a/chromium/content/browser/resources/media/util.js b/chromium/content/browser/resources/media/util.js
index c61ae0e9793..29cc1b152e3 100644
--- a/chromium/content/browser/resources/media/util.js
+++ b/chromium/content/browser/resources/media/util.js
@@ -1,74 +1,47 @@
-// 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.
-cr.define('media', function() {
- 'use strict';
+/**
+ * @fileoverview Some utility functions that don't belong anywhere else in the
+ * code.
+ */
+var util = (function() {
+ var util = {};
+ util.object = {};
/**
- * The width and height of a bar drawn on a file canvas in pixels.
+ * Calls a function for each element in an object/map/hash.
+ *
+ * @param obj The object to iterate over.
+ * @param f The function to call on every value in the object. F should have
+ * the following arguments: f(value, key, object) where value is the value
+ * of the property, key is the corresponding key, and obj is the object that
+ * was passed in originally.
+ * @param optObj The object use as 'this' within f.
*/
- var BAR_WIDTH = 500;
- var BAR_HEIGHT = 16;
-
- /**
- * Draws a 1px white horizontal line across |context|.
- */
- function drawLine(context, top) {
- context.moveTo(0, top);
- context.lineTo(BAR_WIDTH, top);
- context.strokeStyle = '#fff';
- context.stroke();
- }
-
- /**
- * Creates an HTMLElement of type |type| with textContent |content|.
- * @param {string} type The type of element to create.
- * @param {string} content The content to place in the element.
- * @return {HTMLElement} A newly initialized element.
- */
- function makeElement(type, content) {
- var element = document.createElement(type);
- element.textContent = content;
- return element;
- }
-
- /**
- * Creates a new <li> containing a <details> with a <summary> and sets
- * properties to reference them.
- * @return {Object} The new <li>.
- */
- function createDetailsLi() {
- var li = document.createElement('li');
- li.details = document.createElement('details');
- li.summary = document.createElement('summary');
- li.appendChild(li.details);
- li.details.appendChild(li.summary);
- return li
- }
-
- /**
- * Appends each key-value pair in a dictionary to a row in a table.
- * @param {Object} dict The dictionary to append.
- * @param {HTMLElement} table The <table> element to append to.
- */
- function appendDictionaryToTable(dict, table) {
- table.textContent = '';
- for (var key in dict) {
- var tr = document.createElement('tr');
- tr.appendChild(makeElement('td', key + ':'));
- tr.appendChild(makeElement('td', dict[key]));
- table.appendChild(tr);
+ util.object.forEach = function(obj, f, optObj) {
+ 'use strict';
+ var key;
+ for (key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ f.call(optObj, obj[key], key, obj);
+ }
+ }
+ };
+ util.millisecondsToString = function(timeMillis) {
+ function pad(num) {
+ num = num.toString();
+ if (num.length < 2) {
+ return '0' + num;
+ }
+ return num;
}
- return table;
- }
- return {
- BAR_WIDTH: BAR_WIDTH,
- BAR_HEIGHT: BAR_HEIGHT,
- drawLine: drawLine,
- makeElement: makeElement,
- createDetailsLi: createDetailsLi,
- appendDictionaryToTable: appendDictionaryToTable
+ var date = new Date(timeMillis);
+ return pad(date.getUTCHours()) + ':' + pad(date.getUTCMinutes()) + ':' +
+ pad(date.getUTCSeconds()) + ' ' + pad((date.getMilliseconds()) % 1000);
};
-});
+
+ return util;
+}());
diff --git a/chromium/content/browser/resources/media/webrtc_internals.js b/chromium/content/browser/resources/media/webrtc_internals.js
index fd2d34a3faf..5bc56da3ebe 100644
--- a/chromium/content/browser/resources/media/webrtc_internals.js
+++ b/chromium/content/browser/resources/media/webrtc_internals.js
@@ -225,6 +225,8 @@ function updateAllPeerConnections(data) {
var peerConnection = addPeerConnection(data[i]);
var log = data[i].log;
+ if (!log)
+ continue;
for (var j = 0; j < log.length; ++j) {
addPeerConnectionUpdate(peerConnection, log[j]);
}
diff --git a/chromium/content/browser/security_exploit_browsertest.cc b/chromium/content/browser/security_exploit_browsertest.cc
index bc554c2bb82..2eb7b51885b 100644
--- a/chromium/content/browser/security_exploit_browsertest.cc
+++ b/chromium/content/browser/security_exploit_browsertest.cc
@@ -9,7 +9,7 @@
#include "content/public/browser/notification_types.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/test_utils.h"
-#include "content/shell/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
diff --git a/chromium/content/browser/service_worker/OWNERS b/chromium/content/browser/service_worker/OWNERS
new file mode 100644
index 00000000000..633b8a4fd96
--- /dev/null
+++ b/chromium/content/browser/service_worker/OWNERS
@@ -0,0 +1,3 @@
+alecflett@chromium.org
+kinuko@chromium.org
+michaeln@chromium.org
diff --git a/chromium/content/browser/service_worker/service_worker_context.cc b/chromium/content/browser/service_worker/service_worker_context.cc
new file mode 100644
index 00000000000..ed9f669d7f4
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_context.cc
@@ -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.
+
+#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
new file mode 100644
index 00000000000..5b290b7a317
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_context.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_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;
+}
+
+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> {
+ 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);
+
+ private:
+ friend class base::RefCountedThreadSafe<ServiceWorkerContext>;
+ ~ServiceWorkerContext();
+
+ scoped_refptr<quota::QuotaManagerProxy> quota_manager_proxy_;
+ base::FilePath path_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CONTEXT_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
new file mode 100644
index 00000000000..c531e915e88
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_dispatcher_host.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/browser/service_worker/service_worker_dispatcher_host.h"
+
+#include "content/browser/service_worker/service_worker_context.h"
+#include "content/common/service_worker_messages.h"
+#include "ipc/ipc_message_macros.h"
+#include "url/gurl.h"
+
+namespace content {
+
+ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost(
+ ServiceWorkerContext* context)
+ : context_(context) {}
+
+ServiceWorkerDispatcherHost::~ServiceWorkerDispatcherHost() {}
+
+bool ServiceWorkerDispatcherHost::OnMessageReceived(const IPC::Message& message,
+ bool* message_was_ok) {
+
+ if (IPC_MESSAGE_CLASS(message) != ServiceWorkerMsgStart)
+ return false;
+
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP_EX(
+ ServiceWorkerDispatcherHost, message, *message_was_ok)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_RegisterServiceWorker,
+ OnRegisterServiceWorker)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_UnregisterServiceWorker,
+ OnUnregisterServiceWorker)
+ 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::OnUnregisterServiceWorker(
+ int32 registry_id,
+ const string16& scope) {}
+
+} // 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
new file mode 100644
index 00000000000..36927819f69
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_dispatcher_host.h
@@ -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.
+
+#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DISPATCHER_HOST_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DISPATCHER_HOST_H_
+
+#include "content/public/browser/browser_message_filter.h"
+
+class GURL;
+
+namespace content {
+
+class ServiceWorkerContext;
+
+class ServiceWorkerDispatcherHost : public BrowserMessageFilter {
+ public:
+ explicit ServiceWorkerDispatcherHost(ServiceWorkerContext* context);
+
+ // BrowserIOMessageFilter implementation
+ virtual bool OnMessageReceived(const IPC::Message& message,
+ bool* message_was_ok) OVERRIDE;
+
+ protected:
+ virtual ~ServiceWorkerDispatcherHost();
+
+ private:
+ // IPC Message handlers
+
+ void OnRegisterServiceWorker(int32 registry_id,
+ const string16& scope,
+ const GURL& script_url);
+ void OnUnregisterServiceWorker(int32 registry_id, const string16& scope);
+
+ scoped_refptr<ServiceWorkerContext> context_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DISPATCHER_HOST_H_
diff --git a/chromium/content/browser/session_history_browsertest.cc b/chromium/content/browser/session_history_browsertest.cc
index d0bd95001a8..7d006b606f6 100644
--- a/chromium/content/browser/session_history_browsertest.cc
+++ b/chromium/content/browser/session_history_browsertest.cc
@@ -12,7 +12,7 @@
#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_utils.h"
-#include "content/shell/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
@@ -89,7 +89,7 @@ class SessionHistoryTest : public ContentBrowserTest {
}
GURL GetTabURL() {
- return shell()->web_contents()->GetURL();
+ return shell()->web_contents()->GetLastCommittedURL();
}
GURL GetURL(const std::string file) {
diff --git a/chromium/content/browser/site_instance_impl.cc b/chromium/content/browser/site_instance_impl.cc
index 42680674d76..ade96cba840 100644
--- a/chromium/content/browser/site_instance_impl.cc
+++ b/chromium/content/browser/site_instance_impl.cc
@@ -26,7 +26,7 @@ static bool IsURLSameAsAnySiteInstance(const GURL& url) {
// We treat javascript: as the same site as any URL since it is actually
// a modifier on existing pages.
- if (url.SchemeIs(chrome::kJavaScriptScheme))
+ if (url.SchemeIs(kJavaScriptScheme))
return true;
return url == GURL(kChromeUICrashURL) ||
diff --git a/chromium/content/browser/site_per_process_browsertest.cc b/chromium/content/browser/site_per_process_browsertest.cc
index 3485fc51fed..e37ac97cce8 100644
--- a/chromium/content/browser/site_per_process_browsertest.cc
+++ b/chromium/content/browser/site_per_process_browsertest.cc
@@ -13,7 +13,7 @@
#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/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
diff --git a/chromium/content/browser/speech/OWNERS b/chromium/content/browser/speech/OWNERS
index b38caa6f1ff..2c6195ec94b 100644
--- a/chromium/content/browser/speech/OWNERS
+++ b/chromium/content/browser/speech/OWNERS
@@ -1,3 +1,4 @@
hans@chromium.org
+primiano@chromium.org
tommi@chromium.org
xians@chromium.org
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 08a3df7cdb7..397250631fb 100644
--- a/chromium/content/browser/speech/google_streaming_remote_engine_unittest.cc
+++ b/chromium/content/browser/speech/google_streaming_remote_engine_unittest.cc
@@ -6,7 +6,9 @@
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
+#include "base/safe_numerics.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/sys_byteorder.h"
#include "content/browser/speech/audio_buffer.h"
#include "content/browser/speech/google_streaming_remote_engine.h"
#include "content/browser/speech/proto/google_streaming_api.pb.h"
@@ -17,6 +19,8 @@
#include "net/url_request/url_request_status.h"
#include "testing/gtest/include/gtest/gtest.h"
+using base::HostToNet32;
+using base::checked_numeric_cast;
using net::URLRequestStatus;
using net::TestURLFetcher;
using net::TestURLFetcherFactory;
@@ -62,7 +66,6 @@ class GoogleStreamingRemoteEngineTest : public SpeechRecognitionEngineDelegate,
const SpeechRecognitionResults& b);
static std::string SerializeProtobufResponse(
const proto::SpeechRecognitionEvent& msg);
- static std::string ToBigEndian32(uint32 value);
TestURLFetcher* GetUpstreamFetcher();
TestURLFetcher* GetDownstreamFetcher();
@@ -487,17 +490,10 @@ std::string GoogleStreamingRemoteEngineTest::SerializeProtobufResponse(
// Prepend 4 byte prefix length indication to the protobuf message as
// envisaged by the google streaming recognition webservice protocol.
- msg_string.insert(0, ToBigEndian32(msg_string.size()));
- return msg_string;
-}
+ uint32 prefix = HostToNet32(checked_numeric_cast<uint32>(msg_string.size()));
+ msg_string.insert(0, reinterpret_cast<char*>(&prefix), sizeof(prefix));
-std::string GoogleStreamingRemoteEngineTest::ToBigEndian32(uint32 value) {
- char raw_data[4];
- raw_data[0] = static_cast<uint8>((value >> 24) & 0xFF);
- raw_data[1] = static_cast<uint8>((value >> 16) & 0xFF);
- raw_data[2] = static_cast<uint8>((value >> 8) & 0xFF);
- raw_data[3] = static_cast<uint8>(value & 0xFF);
- return std::string(raw_data, sizeof(raw_data));
+ return msg_string;
}
} // namespace content
diff --git a/chromium/content/browser/speech/speech_recognition_browsertest.cc b/chromium/content/browser/speech/input_tag_speech_browsertest.cc
index 8e4c7a84ed7..0a1b2a9ca86 100644
--- a/chromium/content/browser/speech/speech_recognition_browsertest.cc
+++ b/chromium/content/browser/speech/input_tag_speech_browsertest.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.
@@ -18,14 +18,14 @@
#include "content/public/common/url_constants.h"
#include "content/public/test/fake_speech_recognition_manager.h"
#include "content/public/test/test_utils.h"
-#include "content/shell/shell.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"
namespace content {
-class SpeechRecognitionBrowserTest : public ContentBrowserTest {
+class InputTagSpeechBrowserTest : public ContentBrowserTest {
public:
// ContentBrowserTest methods
virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
@@ -69,7 +69,7 @@ class SpeechRecognitionBrowserTest : public ContentBrowserTest {
// then sets the URL fragment as 'pass' if it received the expected string.
LoadAndStartSpeechRecognitionTest(filename);
- EXPECT_EQ("pass", shell()->web_contents()->GetURL().ref());
+ EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
}
// ContentBrowserTest methods.
@@ -94,7 +94,7 @@ class SpeechRecognitionBrowserTest : public ContentBrowserTest {
};
SpeechRecognitionManager*
- SpeechRecognitionBrowserTest::speech_recognition_manager_ = NULL;
+ InputTagSpeechBrowserTest::speech_recognition_manager_ = NULL;
// TODO(satish): Once this flakiness has been fixed, add a second test here to
// check for sending many clicks in succession to the speech button and verify
@@ -105,19 +105,19 @@ SpeechRecognitionManager*
// another test here to check that when speech recognition is in progress and
// a renderer crashes, we get a call to
// SpeechRecognitionManager::CancelAllRequestsWithDelegate.
-IN_PROC_BROWSER_TEST_F(SpeechRecognitionBrowserTest, TestBasicRecognition) {
+IN_PROC_BROWSER_TEST_F(InputTagSpeechBrowserTest, TestBasicRecognition) {
RunSpeechRecognitionTest("basic_recognition.html");
EXPECT_TRUE(fake_speech_recognition_manager_.grammar().empty());
}
-IN_PROC_BROWSER_TEST_F(SpeechRecognitionBrowserTest, GrammarAttribute) {
+IN_PROC_BROWSER_TEST_F(InputTagSpeechBrowserTest, GrammarAttribute) {
RunSpeechRecognitionTest("grammar_attribute.html");
EXPECT_EQ("http://example.com/grammar.xml",
fake_speech_recognition_manager_.grammar());
}
// Flaky on Linux, Windows and Mac http://crbug.com/140765.
-IN_PROC_BROWSER_TEST_F(SpeechRecognitionBrowserTest, DISABLED_TestCancelAll) {
+IN_PROC_BROWSER_TEST_F(InputTagSpeechBrowserTest, DISABLED_TestCancelAll) {
// The test checks that the cancel-all callback gets issued when a session
// is pending, so don't send a fake response.
// We are not expecting a navigation event being raised from the JS of the
diff --git a/chromium/content/browser/speech/speech_recognizer_impl.cc b/chromium/content/browser/speech/speech_recognizer_impl.cc
index 2081b2f982d..2dae43087eb 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl.cc
+++ b/chromium/content/browser/speech/speech_recognizer_impl.cc
@@ -564,7 +564,7 @@ SpeechRecognizerImpl::StartRecording(const FSMEventArgs&) {
new OnDataConverter(input_parameters, output_parameters));
audio_controller_ = AudioInputController::Create(
- audio_manager, this, input_parameters, device_id_);
+ audio_manager, this, input_parameters, device_id_, NULL);
if (!audio_controller_.get()) {
return Abort(SpeechRecognitionError(SPEECH_RECOGNITION_ERROR_AUDIO));
diff --git a/chromium/content/browser/ssl/ssl_manager.cc b/chromium/content/browser/ssl/ssl_manager.cc
index c86dccdcda6..42ee02fbb1c 100644
--- a/chromium/content/browser/ssl/ssl_manager.cc
+++ b/chromium/content/browser/ssl/ssl_manager.cc
@@ -21,8 +21,6 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/load_from_memory_cache_details.h"
#include "content/public/browser/navigation_details.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_source.h"
#include "content/public/browser/resource_request_details.h"
#include "content/public/common/ssl_status.h"
#include "net/url_request/url_request.h"
@@ -99,17 +97,6 @@ SSLManager::SSLManager(NavigationControllerImpl* controller)
controller_(controller) {
DCHECK(controller_);
- // Subscribe to various notifications.
- registrar_.Add(
- this, NOTIFICATION_RESOURCE_RESPONSE_STARTED,
- Source<WebContents>(controller_->web_contents()));
- registrar_.Add(
- this, NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
- Source<WebContents>(controller_->web_contents()));
- registrar_.Add(
- this, NOTIFICATION_LOAD_FROM_MEMORY_CACHE,
- Source<NavigationController>(controller_));
-
SSLManagerSet* managers = static_cast<SSLManagerSet*>(
controller_->GetBrowserContext()->GetUserData(kSSLManagerKeyName));
if (!managers) {
@@ -125,22 +112,18 @@ SSLManager::~SSLManager() {
managers->get().erase(this);
}
-void SSLManager::DidCommitProvisionalLoad(
- const NotificationDetails& in_details) {
- LoadCommittedDetails* details =
- Details<LoadCommittedDetails>(in_details).ptr();
-
+void SSLManager::DidCommitProvisionalLoad(const LoadCommittedDetails& details) {
NavigationEntryImpl* entry =
NavigationEntryImpl::FromNavigationEntry(controller_->GetActiveEntry());
- if (details->is_main_frame) {
+ if (details.is_main_frame) {
if (entry) {
// Decode the security details.
int ssl_cert_id;
net::CertStatus ssl_cert_status;
int ssl_security_bits;
int ssl_connection_status;
- DeserializeSecurityInfo(details->serialized_security_info,
+ DeserializeSecurityInfo(details.serialized_security_info,
&ssl_cert_id,
&ssl_cert_status,
&ssl_security_bits,
@@ -171,52 +154,32 @@ void SSLManager::DidRunInsecureContent(const std::string& security_origin) {
UpdateEntry(navigation_entry);
}
-void SSLManager::Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- // Dispatch by type.
- switch (type) {
- case NOTIFICATION_RESOURCE_RESPONSE_STARTED:
- DidStartResourceResponse(
- Details<ResourceRequestDetails>(details).ptr());
- break;
- case NOTIFICATION_RESOURCE_RECEIVED_REDIRECT:
- DidReceiveResourceRedirect(
- Details<ResourceRedirectDetails>(details).ptr());
- break;
- case NOTIFICATION_LOAD_FROM_MEMORY_CACHE:
- DidLoadFromMemoryCache(
- Details<LoadFromMemoryCacheDetails>(details).ptr());
- break;
- default:
- NOTREACHED() << "The SSLManager received an unexpected notification.";
- }
-}
-
-void SSLManager::DidLoadFromMemoryCache(LoadFromMemoryCacheDetails* details) {
+void SSLManager::DidLoadFromMemoryCache(
+ const LoadFromMemoryCacheDetails& details) {
// Simulate loading this resource through the usual path.
// Note that we specify SUB_RESOURCE as the resource type as WebCore only
// caches sub-resources.
// This resource must have been loaded with no filtering because filtered
// resouces aren't cachable.
scoped_refptr<SSLRequestInfo> info(new SSLRequestInfo(
- details->url,
+ details.url,
ResourceType::SUB_RESOURCE,
- details->pid,
- details->cert_id,
- details->cert_status));
+ details.pid,
+ details.cert_id,
+ details.cert_status));
// Simulate loading this resource through the usual path.
policy()->OnRequestStarted(info.get());
}
-void SSLManager::DidStartResourceResponse(ResourceRequestDetails* details) {
+void SSLManager::DidStartResourceResponse(
+ const ResourceRequestDetails& details) {
scoped_refptr<SSLRequestInfo> info(new SSLRequestInfo(
- details->url,
- details->resource_type,
- details->origin_child_id,
- details->ssl_cert_id,
- details->ssl_cert_status));
+ details.url,
+ details.resource_type,
+ details.origin_child_id,
+ details.ssl_cert_id,
+ details.ssl_cert_status));
// Notify our policy that we started a resource request. Ideally, the
// policy should have the ability to cancel the request, but we can't do
@@ -224,7 +187,8 @@ void SSLManager::DidStartResourceResponse(ResourceRequestDetails* details) {
policy()->OnRequestStarted(info.get());
}
-void SSLManager::DidReceiveResourceRedirect(ResourceRedirectDetails* details) {
+void SSLManager::DidReceiveResourceRedirect(
+ const ResourceRedirectDetails& details) {
// TODO(abarth): Make sure our redirect behavior is correct. If we ever see a
// non-HTTPS resource in the redirect chain, we want to trigger
// insecure content, even if the redirect chain goes back to
diff --git a/chromium/content/browser/ssl/ssl_manager.h b/chromium/content/browser/ssl/ssl_manager.h
index 6c80edd8c04..45100a7ea62 100644
--- a/chromium/content/browser/ssl/ssl_manager.h
+++ b/chromium/content/browser/ssl/ssl_manager.h
@@ -14,8 +14,6 @@
#include "content/browser/ssl/ssl_policy_backend.h"
#include "content/common/content_export.h"
#include "content/public/browser/global_request_id.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
#include "net/base/net_errors.h"
#include "net/cert/cert_status_flags.h"
#include "url/gurl.h"
@@ -29,6 +27,7 @@ class BrowserContext;
class NavigationEntryImpl;
class NavigationControllerImpl;
class SSLPolicy;
+struct LoadCommittedDetails;
struct LoadFromMemoryCacheDetails;
struct ResourceRedirectDetails;
struct ResourceRequestDetails;
@@ -41,7 +40,7 @@ struct ResourceRequestDetails;
// The security state (secure/insecure) is stored in the navigation entry.
// Along with it are stored any SSL error code and the associated cert.
-class SSLManager : public NotificationObserver {
+class SSLManager {
public:
// Entry point for SSLCertificateErrors. This function begins the process
// of resolving a certificate error during an SSL connection. SSLManager
@@ -74,32 +73,16 @@ class SSLManager : public NotificationObserver {
// NavigationController is guaranteed to outlive the SSLManager.
NavigationControllerImpl* controller() { return controller_; }
- // This entry point is called directly (instead of via the notification
- // service) because we need more precise control of the order in which folks
- // are notified of this event.
- void DidCommitProvisionalLoad(const NotificationDetails& details);
+ void DidCommitProvisionalLoad(const LoadCommittedDetails& details);
+ void DidLoadFromMemoryCache(const LoadFromMemoryCacheDetails& details);
+ void DidStartResourceResponse(const ResourceRequestDetails& details);
+ void DidReceiveResourceRedirect(const ResourceRedirectDetails& details);
// Insecure content entry point.
void DidDisplayInsecureContent();
void DidRunInsecureContent(const std::string& security_origin);
- // Entry point for navigation. This function begins the process of updating
- // the security UI when the main frame navigates to a new URL.
- //
- // Called on the UI thread.
- virtual void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) OVERRIDE;
-
private:
- // Entry points for notifications to which we subscribe. Note that
- // DidCommitProvisionalLoad uses the abstract NotificationDetails type since
- // the type we need is in NavigationController which would create a circular
- // header file dependency.
- void DidLoadFromMemoryCache(LoadFromMemoryCacheDetails* details);
- void DidStartResourceResponse(ResourceRequestDetails* details);
- void DidReceiveResourceRedirect(ResourceRedirectDetails* details);
-
// Update the NavigationEntry with our current state.
void UpdateEntry(NavigationEntryImpl* entry);
@@ -113,9 +96,6 @@ class SSLManager : public NotificationObserver {
// for the security UI of this tab.
NavigationControllerImpl* controller_;
- // Handles registering notifications with the NotificationService.
- NotificationRegistrar registrar_;
-
DISALLOW_COPY_AND_ASSIGN(SSLManager);
};
diff --git a/chromium/content/browser/startup_task_runner.cc b/chromium/content/browser/startup_task_runner.cc
index a7e730e5d87..4746afea6b0 100644
--- a/chromium/content/browser/startup_task_runner.cc
+++ b/chromium/content/browser/startup_task_runner.cc
@@ -11,53 +11,72 @@
namespace content {
StartupTaskRunner::StartupTaskRunner(
- bool browser_may_start_asynchronously,
base::Callback<void(int)> const startup_complete_callback,
scoped_refptr<base::SingleThreadTaskRunner> proxy)
- : asynchronous_startup_(browser_may_start_asynchronously),
- startup_complete_callback_(startup_complete_callback),
- proxy_(proxy) {}
+ : startup_complete_callback_(startup_complete_callback), proxy_(proxy) {}
+
+StartupTaskRunner::~StartupTaskRunner() {}
void StartupTaskRunner::AddTask(StartupTask& callback) {
task_list_.push_back(callback);
}
-void StartupTaskRunner::StartRunningTasks() {
+void StartupTaskRunner::StartRunningTasksAsync() {
DCHECK(proxy_);
int result = 0;
- if (asynchronous_startup_ && !task_list_.empty()) {
- const base::Closure next_task =
- base::Bind(&StartupTaskRunner::WrappedTask, this);
- proxy_->PostNonNestableTask(FROM_HERE, next_task);
- } else {
- for (std::list<StartupTask>::iterator it = task_list_.begin();
- it != task_list_.end();
- it++) {
- result = it->Run();
- if (result > 0) {
- break;
- }
- }
+ if (task_list_.empty()) {
if (!startup_complete_callback_.is_null()) {
startup_complete_callback_.Run(result);
+ // Clear the callback to prevent it being called a second time
+ startup_complete_callback_.Reset();
}
+ } else {
+ const base::Closure next_task =
+ base::Bind(&StartupTaskRunner::WrappedTask, base::Unretained(this));
+ proxy_->PostNonNestableTask(FROM_HERE, next_task);
+ }
+}
+
+void StartupTaskRunner::RunAllTasksNow() {
+ int result = 0;
+ for (std::list<StartupTask>::iterator it = task_list_.begin();
+ it != task_list_.end();
+ it++) {
+ result = it->Run();
+ if (result > 0) break;
+ }
+ task_list_.clear();
+ if (!startup_complete_callback_.is_null()) {
+ startup_complete_callback_.Run(result);
+ // Clear the callback to prevent it being called a second time
+ startup_complete_callback_.Reset();
}
}
void StartupTaskRunner::WrappedTask() {
+ if (task_list_.empty()) {
+ // This will happen if the remaining tasks have been run synchronously since
+ // the WrappedTask was created. Any callback will already have been called,
+ // so there is nothing to do
+ return;
+ }
int result = task_list_.front().Run();
task_list_.pop_front();
- if (result > 0 || task_list_.empty()) {
+ if (result > 0) {
+ // Stop now and throw away the remaining tasks
+ task_list_.clear();
+ }
+ if (task_list_.empty()) {
if (!startup_complete_callback_.is_null()) {
startup_complete_callback_.Run(result);
+ // Clear the callback to prevent it being called a second time
+ startup_complete_callback_.Reset();
}
} else {
const base::Closure next_task =
- base::Bind(&StartupTaskRunner::WrappedTask, this);
+ base::Bind(&StartupTaskRunner::WrappedTask, base::Unretained(this));
proxy_->PostNonNestableTask(FROM_HERE, next_task);
}
}
-StartupTaskRunner::~StartupTaskRunner() {}
-
} // namespace content
diff --git a/chromium/content/browser/startup_task_runner.h b/chromium/content/browser/startup_task_runner.h
index 5f954edc887..80e5627803f 100644
--- a/chromium/content/browser/startup_task_runner.h
+++ b/chromium/content/browser/startup_task_runner.h
@@ -8,7 +8,6 @@
#include <list>
#include "base/callback.h"
-#include "base/memory/ref_counted.h"
#include "base/single_thread_task_runner.h"
#include "build/build_config.h"
@@ -32,30 +31,31 @@ typedef base::Callback<int(void)> StartupTask;
// no opportunity to handle UI events between the tasks of a
// SingleThreadedTaskRunner.
-class CONTENT_EXPORT StartupTaskRunner
- : public base::RefCounted<StartupTaskRunner> {
+class CONTENT_EXPORT StartupTaskRunner {
public:
// Constructor: Note that |startup_complete_callback| is optional. If it is
// not null it will be called once all the startup tasks have run.
- StartupTaskRunner(bool browser_may_start_asynchronously,
- base::Callback<void(int)> startup_complete_callback,
+ StartupTaskRunner(base::Callback<void(int)> startup_complete_callback,
scoped_refptr<base::SingleThreadTaskRunner> proxy);
+ ~StartupTaskRunner();
+
// Add a task to the queue of startup tasks to be run.
- virtual void AddTask(StartupTask& callback);
+ void AddTask(StartupTask& callback);
+
+ // Start running the tasks asynchronously.
+ void StartRunningTasksAsync();
- // Start running the tasks.
- virtual void StartRunningTasks();
+ // Run all tasks, or all remaining tasks, synchronously
+ void RunAllTasksNow();
private:
friend class base::RefCounted<StartupTaskRunner>;
- virtual ~StartupTaskRunner();
std::list<StartupTask> task_list_;
void WrappedTask();
- const bool asynchronous_startup_;
base::Callback<void(int)> startup_complete_callback_;
scoped_refptr<base::SingleThreadTaskRunner> proxy_;
diff --git a/chromium/content/browser/startup_task_runner_unittest.cc b/chromium/content/browser/startup_task_runner_unittest.cc
index 2efa79f7ac6..fcd2b3d1da6 100644
--- a/chromium/content/browser/startup_task_runner_unittest.cc
+++ b/chromium/content/browser/startup_task_runner_unittest.cc
@@ -23,7 +23,8 @@ using testing::Assign;
using testing::Invoke;
using testing::WithArg;
-bool observer_called = false;
+int observer_calls = 0;
+int task_count = 0;
int observer_result;
base::Closure task;
@@ -35,7 +36,7 @@ bool SaveTaskArg(const Closure& arg) {
}
void Observer(int result) {
- observer_called = true;
+ observer_calls++;
observer_result = result;
}
@@ -44,22 +45,26 @@ class StartupTaskRunnerTest : public testing::Test {
virtual void SetUp() {
last_task_ = 0;
- observer_called = false;
+ observer_calls = 0;
+ task_count = 0;
}
int Task1() {
last_task_ = 1;
+ task_count++;
return 0;
}
int Task2() {
last_task_ = 2;
+ task_count++;
return 0;
}
int FailingTask() {
// Task returning failure
last_task_ = 3;
+ task_count++;
return 1;
}
@@ -116,26 +121,35 @@ TEST_F(StartupTaskRunnerTest, SynchronousExecution) {
EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0);
EXPECT_CALL(mock_runner, PostNonNestableDelayedTask(_, _, _)).Times(0);
- scoped_refptr<StartupTaskRunner> runner =
- new StartupTaskRunner(false, base::Bind(&Observer), proxy);
+ StartupTaskRunner runner(base::Bind(&Observer), proxy);
StartupTask task1 =
base::Bind(&StartupTaskRunnerTest::Task1, base::Unretained(this));
- runner->AddTask(task1);
+ runner.AddTask(task1);
EXPECT_EQ(GetLastTask(), 0);
StartupTask task2 =
base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
- runner->AddTask(task2);
+ runner.AddTask(task2);
// Nothing should run until we tell them to.
EXPECT_EQ(GetLastTask(), 0);
- runner->StartRunningTasks();
+ runner.RunAllTasksNow();
// On an immediate StartupTaskRunner the tasks should now all have run.
EXPECT_EQ(GetLastTask(), 2);
- EXPECT_TRUE(observer_called);
+ EXPECT_EQ(task_count, 2);
+ EXPECT_EQ(observer_calls, 1);
EXPECT_EQ(observer_result, 0);
+
+ // Running the tasks asynchronously shouldn't do anything
+ // In particular Post... should not be called
+ runner.StartRunningTasksAsync();
+
+ // No more tasks should be run and the observer should not have been called
+ // again
+ EXPECT_EQ(task_count, 2);
+ EXPECT_EQ(observer_calls, 1);
}
TEST_F(StartupTaskRunnerTest, NullObserver) {
@@ -145,25 +159,32 @@ TEST_F(StartupTaskRunnerTest, NullObserver) {
EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0);
EXPECT_CALL(mock_runner, PostNonNestableDelayedTask(_, _, _)).Times(0);
- scoped_refptr<StartupTaskRunner> runner =
- new StartupTaskRunner(false, base::Callback<void(int)>(), proxy);
+ StartupTaskRunner runner(base::Callback<void(int)>(), proxy);
StartupTask task1 =
base::Bind(&StartupTaskRunnerTest::Task1, base::Unretained(this));
- runner->AddTask(task1);
+ runner.AddTask(task1);
EXPECT_EQ(GetLastTask(), 0);
StartupTask task2 =
base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
- runner->AddTask(task2);
+ runner.AddTask(task2);
// Nothing should run until we tell them to.
EXPECT_EQ(GetLastTask(), 0);
- runner->StartRunningTasks();
+ runner.RunAllTasksNow();
// On an immediate StartupTaskRunner the tasks should now all have run.
EXPECT_EQ(GetLastTask(), 2);
+ EXPECT_EQ(task_count, 2);
+
+ // Running the tasks asynchronously shouldn't do anything
+ // In particular Post... should not be called
+ runner.StartRunningTasksAsync();
- EXPECT_FALSE(observer_called);
+ // No more tasks should have been run
+ EXPECT_EQ(task_count, 2);
+
+ EXPECT_EQ(observer_calls, 0);
}
TEST_F(StartupTaskRunnerTest, SynchronousExecutionFailedTask) {
@@ -173,26 +194,34 @@ TEST_F(StartupTaskRunnerTest, SynchronousExecutionFailedTask) {
EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0);
EXPECT_CALL(mock_runner, PostNonNestableDelayedTask(_, _, _)).Times(0);
- scoped_refptr<StartupTaskRunner> runner =
- new StartupTaskRunner(false, base::Bind(&Observer), proxy);
+ StartupTaskRunner runner(base::Bind(&Observer), proxy);
StartupTask task3 =
base::Bind(&StartupTaskRunnerTest::FailingTask, base::Unretained(this));
- runner->AddTask(task3);
+ runner.AddTask(task3);
EXPECT_EQ(GetLastTask(), 0);
StartupTask task2 =
base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
- runner->AddTask(task2);
+ runner.AddTask(task2);
// Nothing should run until we tell them to.
EXPECT_EQ(GetLastTask(), 0);
- runner->StartRunningTasks();
+ runner.RunAllTasksNow();
// Only the first task should have run, since it failed
EXPECT_EQ(GetLastTask(), 3);
-
- EXPECT_TRUE(observer_called);
+ EXPECT_EQ(task_count, 1);
+ EXPECT_EQ(observer_calls, 1);
EXPECT_EQ(observer_result, 1);
+
+ // After a failed task all remaining tasks should be cancelled
+ // In particular Post... should not be called by running asynchronously
+ runner.StartRunningTasksAsync();
+
+ // The observer should only be called the first time the queue completes and
+ // no more tasks should have run
+ EXPECT_EQ(observer_calls, 1);
+ EXPECT_EQ(task_count, 1);
}
TEST_F(StartupTaskRunnerTest, AsynchronousExecution) {
@@ -207,19 +236,18 @@ TEST_F(StartupTaskRunnerTest, AsynchronousExecution) {
.Times(testing::Between(2, 3))
.WillRepeatedly(WithArg<1>(Invoke(SaveTaskArg)));
- scoped_refptr<StartupTaskRunner> runner =
- new StartupTaskRunner(true, base::Bind(&Observer), proxy);
+ StartupTaskRunner runner(base::Bind(&Observer), proxy);
StartupTask task1 =
base::Bind(&StartupTaskRunnerTest::Task1, base::Unretained(this));
- runner->AddTask(task1);
+ runner.AddTask(task1);
StartupTask task2 =
base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
- runner->AddTask(task2);
+ runner.AddTask(task2);
// Nothing should run until we tell them to.
EXPECT_EQ(GetLastTask(), 0);
- runner->StartRunningTasks();
+ runner.StartRunningTasksAsync();
// No tasks should have run yet, since we the message loop hasn't run.
EXPECT_EQ(GetLastTask(), 0);
@@ -228,12 +256,19 @@ TEST_F(StartupTaskRunnerTest, AsynchronousExecution) {
// be added to the queue, hence updating "task". The loop should actually run
// at most 3 times (once for each task plus possibly once for the observer),
// the "4" is a backstop.
- for (int i = 0; i < 4 && !observer_called; i++) {
+ for (int i = 0; i < 4 && observer_calls == 0; i++) {
task.Run();
EXPECT_EQ(i + 1, GetLastTask());
}
- EXPECT_TRUE(observer_called);
+ EXPECT_EQ(task_count, 2);
+ EXPECT_EQ(observer_calls, 1);
EXPECT_EQ(observer_result, 0);
+
+ // Check that running synchronously now doesn't do anything
+
+ runner.RunAllTasksNow();
+ EXPECT_EQ(task_count, 2);
+ EXPECT_EQ(observer_calls, 1);
}
TEST_F(StartupTaskRunnerTest, AsynchronousExecutionFailedTask) {
@@ -248,19 +283,18 @@ TEST_F(StartupTaskRunnerTest, AsynchronousExecutionFailedTask) {
.Times(testing::Between(1, 2))
.WillRepeatedly(WithArg<1>(Invoke(SaveTaskArg)));
- scoped_refptr<StartupTaskRunner> runner =
- new StartupTaskRunner(true, base::Bind(&Observer), proxy);
+ StartupTaskRunner runner(base::Bind(&Observer), proxy);
StartupTask task3 =
base::Bind(&StartupTaskRunnerTest::FailingTask, base::Unretained(this));
- runner->AddTask(task3);
+ runner.AddTask(task3);
StartupTask task2 =
base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
- runner->AddTask(task2);
+ runner.AddTask(task2);
// Nothing should run until we tell them to.
EXPECT_EQ(GetLastTask(), 0);
- runner->StartRunningTasks();
+ runner.StartRunningTasksAsync();
// No tasks should have run yet, since we the message loop hasn't run.
EXPECT_EQ(GetLastTask(), 0);
@@ -269,13 +303,19 @@ TEST_F(StartupTaskRunnerTest, AsynchronousExecutionFailedTask) {
// be added to the queue, hence updating "task". The loop should actually run
// at most twice (once for the failed task plus possibly once for the
// observer), the "4" is a backstop.
- for (int i = 0; i < 4 && !observer_called; i++) {
+ for (int i = 0; i < 4 && observer_calls == 0; i++) {
task.Run();
}
EXPECT_EQ(GetLastTask(), 3);
+ EXPECT_EQ(task_count, 1);
- EXPECT_TRUE(observer_called);
+ EXPECT_EQ(observer_calls, 1);
EXPECT_EQ(observer_result, 1);
+
+ // Check that running synchronously now doesn't do anything
+ runner.RunAllTasksNow();
+ EXPECT_EQ(observer_calls, 1);
+ EXPECT_EQ(task_count, 1);
}
} // namespace
} // namespace content
diff --git a/chromium/content/browser/storage_partition_impl.cc b/chromium/content/browser/storage_partition_impl.cc
index c5471869150..e984e617343 100644
--- a/chromium/content/browser/storage_partition_impl.cc
+++ b/chromium/content/browser/storage_partition_impl.cc
@@ -112,7 +112,6 @@ void ClearQuotaManagedOriginsOnIOThread(quota::QuotaManager* quota_manager,
return;
}
- std::set<GURL>::const_iterator origin;
size_t* origins_to_delete_count = new size_t(origins.size());
for (std::set<GURL>::const_iterator origin = origins.begin();
origin != origins.end(); ++origin) {
@@ -285,6 +284,7 @@ StoragePartitionImpl::StoragePartitionImpl(
webkit_database::DatabaseTracker* database_tracker,
DOMStorageContextWrapper* dom_storage_context,
IndexedDBContextImpl* indexed_db_context,
+ ServiceWorkerContext* service_worker_context,
WebRTCIdentityStore* webrtc_identity_store)
: partition_path_(partition_path),
quota_manager_(quota_manager),
@@ -293,6 +293,7 @@ StoragePartitionImpl::StoragePartitionImpl(
database_tracker_(database_tracker),
dom_storage_context_(dom_storage_context),
indexed_db_context_(indexed_db_context),
+ service_worker_context_(service_worker_context),
webrtc_identity_store_(webrtc_identity_store) {}
StoragePartitionImpl::~StoragePartitionImpl() {
@@ -368,6 +369,9 @@ StoragePartitionImpl* StoragePartitionImpl::Create(
quota_manager->proxy(),
idb_task_runner);
+ scoped_refptr<ServiceWorkerContext> service_worker_context =
+ new ServiceWorkerContext(path, quota_manager->proxy());
+
scoped_refptr<ChromeAppCacheService> appcache_service =
new ChromeAppCacheService(quota_manager->proxy());
@@ -381,6 +385,7 @@ StoragePartitionImpl* StoragePartitionImpl::Create(
database_tracker.get(),
dom_storage_context.get(),
indexed_db_context.get(),
+ service_worker_context.get(),
webrtc_identity_store.get());
}
@@ -421,6 +426,10 @@ IndexedDBContextImpl* StoragePartitionImpl::GetIndexedDBContext() {
return indexed_db_context_.get();
}
+ServiceWorkerContext* StoragePartitionImpl::GetServiceWorkerContext() {
+ return service_worker_context_.get();
+}
+
void StoragePartitionImpl::ClearDataImpl(
uint32 remove_mask,
uint32 quota_storage_remove_mask,
diff --git a/chromium/content/browser/storage_partition_impl.h b/chromium/content/browser/storage_partition_impl.h
index e59347cb569..87130e10bd8 100644
--- a/chromium/content/browser/storage_partition_impl.h
+++ b/chromium/content/browser/storage_partition_impl.h
@@ -12,6 +12,7 @@
#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/common/content_export.h"
#include "content/public/browser/storage_partition.h"
@@ -46,6 +47,8 @@ class StoragePartitionImpl : public StoragePartition {
const base::Time& end,
const base::Closure& callback) OVERRIDE;
+ ServiceWorkerContext* GetServiceWorkerContext();
+
WebRTCIdentityStore* GetWebRTCIdentityStore();
struct DataDeletionHelper;
@@ -77,6 +80,7 @@ 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);
void ClearDataImpl(uint32 remove_mask,
@@ -112,6 +116,7 @@ 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<WebRTCIdentityStore> webrtc_identity_store_;
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 c5721aee667..feb9515fe67 100644
--- a/chromium/content/browser/storage_partition_impl_map.cc
+++ b/chromium/content/browser/storage_partition_impl_map.cc
@@ -34,18 +34,20 @@
#include "crypto/sha2.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
+#include "webkit/browser/blob/blob_storage_context.h"
#include "webkit/browser/blob/blob_url_request_job_factory.h"
#include "webkit/browser/fileapi/file_system_url_request_job_factory.h"
#include "webkit/common/blob/blob_data.h"
using appcache::AppCacheService;
using fileapi::FileSystemContext;
-using webkit_blob::BlobStorageController;
+using webkit_blob::BlobStorageContext;
namespace content {
namespace {
+// A derivative that knows about Streams too.
class BlobProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler {
public:
BlobProtocolHandler(ChromeBlobStorageContext* blob_storage_context,
@@ -53,77 +55,39 @@ class BlobProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler {
fileapi::FileSystemContext* file_system_context)
: blob_storage_context_(blob_storage_context),
stream_context_(stream_context),
- file_system_context_(file_system_context) {}
+ file_system_context_(file_system_context) {
+ }
- virtual ~BlobProtocolHandler() {}
+ virtual ~BlobProtocolHandler() {
+ }
virtual net::URLRequestJob* MaybeCreateJob(
net::URLRequest* request,
net::NetworkDelegate* network_delegate) const OVERRIDE {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- if (!webkit_blob_protocol_handler_impl_) {
- webkit_blob_protocol_handler_impl_.reset(
- new WebKitBlobProtocolHandlerImpl(blob_storage_context_->controller(),
- stream_context_.get(),
- file_system_context_.get()));
+ scoped_refptr<Stream> stream =
+ stream_context_->registry()->GetStream(request->url());
+ if (stream.get())
+ return new StreamURLRequestJob(request, network_delegate, stream);
+
+ if (!blob_protocol_handler_) {
+ // Construction is deferred because 'this' is constructed on
+ // the main thread but we want blob_protocol_handler_ constructed
+ // on the IO thread.
+ blob_protocol_handler_.reset(
+ new webkit_blob::BlobProtocolHandler(
+ blob_storage_context_->context(),
+ file_system_context_,
+ BrowserThread::GetMessageLoopProxyForThread(
+ BrowserThread::FILE).get()));
}
- return webkit_blob_protocol_handler_impl_->MaybeCreateJob(request,
- network_delegate);
+ return blob_protocol_handler_->MaybeCreateJob(request, network_delegate);
}
private:
- // An implementation of webkit_blob::BlobProtocolHandler that gets
- // the BlobData from ResourceRequestInfoImpl.
- class WebKitBlobProtocolHandlerImpl
- : public webkit_blob::BlobProtocolHandler {
- public:
- WebKitBlobProtocolHandlerImpl(
- webkit_blob::BlobStorageController* blob_storage_controller,
- StreamContext* stream_context,
- fileapi::FileSystemContext* file_system_context)
- : webkit_blob::BlobProtocolHandler(
- blob_storage_controller,
- file_system_context,
- BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)
- .get()),
- stream_context_(stream_context) {}
-
- virtual ~WebKitBlobProtocolHandlerImpl() {}
-
- virtual net::URLRequestJob* MaybeCreateJob(
- net::URLRequest* request,
- net::NetworkDelegate* network_delegate) const OVERRIDE {
- scoped_refptr<Stream> stream =
- stream_context_->registry()->GetStream(request->url());
- if (stream.get())
- return new StreamURLRequestJob(request, network_delegate, stream);
-
- return webkit_blob::BlobProtocolHandler::MaybeCreateJob(
- request, network_delegate);
- }
-
- private:
- // webkit_blob::BlobProtocolHandler implementation.
- virtual scoped_refptr<webkit_blob::BlobData>
- LookupBlobData(net::URLRequest* request) const OVERRIDE {
- const ResourceRequestInfoImpl* info =
- ResourceRequestInfoImpl::ForRequest(request);
- if (!info)
- return NULL;
- return info->requested_blob_data();
- }
-
- const scoped_refptr<StreamContext> stream_context_;
- DISALLOW_COPY_AND_ASSIGN(WebKitBlobProtocolHandlerImpl);
- };
-
const scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
const scoped_refptr<StreamContext> stream_context_;
const scoped_refptr<fileapi::FileSystemContext> file_system_context_;
-
- mutable scoped_ptr<WebKitBlobProtocolHandlerImpl>
- webkit_blob_protocol_handler_impl_;
-
+ mutable scoped_ptr<webkit_blob::BlobProtocolHandler> blob_protocol_handler_;
DISALLOW_COPY_AND_ASSIGN(BlobProtocolHandler);
};
diff --git a/chromium/content/browser/storage_partition_impl_unittest.cc b/chromium/content/browser/storage_partition_impl_unittest.cc
index a8b47bc74ca..4828ae6529f 100644
--- a/chromium/content/browser/storage_partition_impl_unittest.cc
+++ b/chromium/content/browser/storage_partition_impl_unittest.cc
@@ -110,7 +110,7 @@ TEST_F(StoragePartitionShaderClearTest, ClearShaderCache) {
TestClosureCallback clear_cb;
StoragePartitionImpl sp(
- cache_path(), NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ cache_path(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
base::MessageLoop::current()->PostTask(
FROM_HERE, base::Bind(&ClearData, &sp, clear_cb.callback()));
clear_cb.WaitForResult();
diff --git a/chromium/content/browser/streams/stream.cc b/chromium/content/browser/streams/stream.cc
index f5abe0276e8..5d20fe6ab64 100644
--- a/chromium/content/browser/streams/stream.cc
+++ b/chromium/content/browser/streams/stream.cc
@@ -23,10 +23,11 @@ namespace content {
Stream::Stream(StreamRegistry* registry,
StreamWriteObserver* write_observer,
const GURL& url)
- : data_bytes_read_(0),
- can_add_data_(true),
+ : can_add_data_(true),
url_(url),
data_length_(0),
+ data_bytes_read_(0),
+ last_total_buffered_bytes_(0),
registry_(registry),
read_observer_(NULL),
write_observer_(write_observer),
@@ -67,19 +68,50 @@ void Stream::RemoveWriteObserver(StreamWriteObserver* observer) {
write_observer_ = NULL;
}
+void Stream::Abort() {
+ // Clear all buffer. It's safe to clear reader_ here since the same thread
+ // is used for both input and output operation.
+ writer_.reset();
+ reader_.reset();
+ ClearBuffer();
+ can_add_data_ = false;
+ registry_->UnregisterStream(url());
+}
+
void Stream::AddData(scoped_refptr<net::IOBuffer> buffer, size_t size) {
+ if (!writer_.get())
+ return;
+
+ size_t current_buffered_bytes = writer_->GetTotalBufferedBytes();
+ if (!registry_->UpdateMemoryUsage(url(), current_buffered_bytes, size)) {
+ Abort();
+ return;
+ }
+
+ // Now it's guaranteed that this doesn't overflow. This must be done before
+ // Write() since GetTotalBufferedBytes() may return different value after
+ // Write() call, so if we use the new value, information in this instance and
+ // one in |registry_| become inconsistent.
+ last_total_buffered_bytes_ = current_buffered_bytes + size;
+
can_add_data_ = writer_->Write(buffer, size);
}
void Stream::AddData(const char* data, size_t size) {
+ if (!writer_.get())
+ return;
+
scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(size));
memcpy(io_buffer->data(), data, size);
- can_add_data_ = writer_->Write(io_buffer, size);
+ AddData(io_buffer, size);
}
void Stream::Finalize() {
+ if (!writer_.get())
+ return;
+
writer_->Close(0);
- writer_.reset(NULL);
+ writer_.reset();
// Continue asynchronously.
base::MessageLoopProxy::current()->PostTask(
@@ -90,10 +122,17 @@ void Stream::Finalize() {
Stream::StreamState Stream::ReadRawData(net::IOBuffer* buf,
int buf_size,
int* bytes_read) {
+ DCHECK(buf);
+ DCHECK(bytes_read);
+
*bytes_read = 0;
if (!data_.get()) {
- data_length_ = 0;
- data_bytes_read_ = 0;
+ DCHECK(!data_length_);
+ DCHECK(!data_bytes_read_);
+
+ if (!reader_.get())
+ return STREAM_ABORTED;
+
ByteStreamReader::StreamState state = reader_->Read(&data_, &data_length_);
switch (state) {
case ByteStreamReader::STREAM_HAS_DATA:
@@ -113,7 +152,7 @@ Stream::StreamState Stream::ReadRawData(net::IOBuffer* buf,
memcpy(buf->data(), data_->data() + data_bytes_read_, to_read);
data_bytes_read_ += to_read;
if (data_bytes_read_ >= data_length_)
- data_ = NULL;
+ ClearBuffer();
*bytes_read = to_read;
return STREAM_HAS_DATA;
@@ -150,4 +189,10 @@ void Stream::OnDataAvailable() {
read_observer_->OnDataAvailable(this);
}
+void Stream::ClearBuffer() {
+ data_ = NULL;
+ data_length_ = 0;
+ data_bytes_read_ = 0;
+}
+
} // namespace content
diff --git a/chromium/content/browser/streams/stream.h b/chromium/content/browser/streams/stream.h
index 85edc884081..3937f5b9e38 100644
--- a/chromium/content/browser/streams/stream.h
+++ b/chromium/content/browser/streams/stream.h
@@ -36,6 +36,7 @@ class CONTENT_EXPORT Stream : public base::RefCountedThreadSafe<Stream> {
STREAM_HAS_DATA,
STREAM_COMPLETE,
STREAM_EMPTY,
+ STREAM_ABORTED,
};
// Creates a stream.
@@ -57,6 +58,10 @@ class CONTENT_EXPORT Stream : public base::RefCountedThreadSafe<Stream> {
// Removes the write observer. |observer| must be the current observer.
void RemoveWriteObserver(StreamWriteObserver* observer);
+ // Stops accepting new data, clears all buffer, unregisters this stream from
+ // |registry_| and make coming ReadRawData() calls return STREAM_ABORTED.
+ void Abort();
+
// Adds the data in |buffer| to the stream. Takes ownership of |buffer|.
void AddData(scoped_refptr<net::IOBuffer> buffer, size_t size);
// Adds data of |size| at |data| to the stream. This method creates a copy
@@ -81,6 +86,11 @@ class CONTENT_EXPORT Stream : public base::RefCountedThreadSafe<Stream> {
const GURL& url() const { return url_; }
+ // For StreamRegistry to remember the last memory usage reported to it.
+ size_t last_total_buffered_bytes() const {
+ return last_total_buffered_bytes_;
+ }
+
private:
friend class base::RefCountedThreadSafe<Stream>;
@@ -89,13 +99,25 @@ class CONTENT_EXPORT Stream : public base::RefCountedThreadSafe<Stream> {
void OnSpaceAvailable();
void OnDataAvailable();
- size_t data_bytes_read_;
+ // Clears |data_| and related variables.
+ void ClearBuffer();
+
bool can_add_data_;
GURL url_;
+ // Buffer for storing data read from |reader_| but not yet read out from this
+ // Stream by ReadRawData() method.
scoped_refptr<net::IOBuffer> data_;
+ // Number of bytes read from |reader_| into |data_| including bytes already
+ // read out.
size_t data_length_;
+ // Number of bytes in |data_| that are already read out.
+ size_t data_bytes_read_;
+
+ // Last value returned by writer_->TotalBufferedBytes() in AddData(). Stored
+ // in order to check memory usage.
+ size_t last_total_buffered_bytes_;
scoped_ptr<ByteStreamWriter> writer_;
scoped_ptr<ByteStreamReader> reader_;
diff --git a/chromium/content/browser/streams/stream_registry.cc b/chromium/content/browser/streams/stream_registry.cc
index 39d24b39f5f..f722f57d03c 100644
--- a/chromium/content/browser/streams/stream_registry.cc
+++ b/chromium/content/browser/streams/stream_registry.cc
@@ -8,7 +8,15 @@
namespace content {
-StreamRegistry::StreamRegistry() {
+namespace {
+// The maximum size of memory each StreamRegistry instance is allowed to use
+// for its Stream instances.
+const size_t kDefaultMaxMemoryUsage = 1024 * 1024 * 1024U; // 1GiB
+}
+
+StreamRegistry::StreamRegistry()
+ : total_memory_usage_(0),
+ max_memory_usage_(kDefaultMaxMemoryUsage) {
}
StreamRegistry::~StreamRegistry() {
@@ -42,7 +50,43 @@ bool StreamRegistry::CloneStream(const GURL& url, const GURL& src_url) {
void StreamRegistry::UnregisterStream(const GURL& url) {
DCHECK(CalledOnValidThread());
+
+ StreamMap::iterator iter = streams_.find(url);
+ if (iter == streams_.end())
+ return;
+
+ // Only update |total_memory_usage_| if |url| is NOT a Stream clone because
+ // cloned streams do not update |total_memory_usage_|.
+ if (iter->second->url() == url) {
+ size_t buffered_bytes = iter->second->last_total_buffered_bytes();
+ DCHECK_LE(buffered_bytes, total_memory_usage_);
+ total_memory_usage_ -= buffered_bytes;
+ }
+
streams_.erase(url);
}
+bool StreamRegistry::UpdateMemoryUsage(const GURL& url,
+ size_t current_size,
+ size_t increase) {
+ DCHECK(CalledOnValidThread());
+
+ StreamMap::iterator iter = streams_.find(url);
+ // A Stream must be registered with its parent registry to get memory.
+ if (iter == streams_.end())
+ return false;
+
+ size_t last_size = iter->second->last_total_buffered_bytes();
+ DCHECK_LE(last_size, total_memory_usage_);
+ size_t usage_of_others = total_memory_usage_ - last_size;
+ DCHECK_LE(current_size, last_size);
+ size_t current_total_memory_usage = usage_of_others + current_size;
+
+ if (increase > max_memory_usage_ - current_total_memory_usage)
+ return false;
+
+ total_memory_usage_ = current_total_memory_usage + increase;
+ return true;
+}
+
} // namespace content
diff --git a/chromium/content/browser/streams/stream_registry.h b/chromium/content/browser/streams/stream_registry.h
index e75c97c1699..a359411d2ae 100644
--- a/chromium/content/browser/streams/stream_registry.h
+++ b/chromium/content/browser/streams/stream_registry.h
@@ -32,20 +32,37 @@ class CONTENT_EXPORT StreamRegistry : public base::NonThreadSafe {
void UnregisterStream(const GURL& url);
+ // Called by Stream instances to request increase of memory usage. If the
+ // total memory usage for this registry is going to exceed the limit,
+ // returns false. Otherwise, updates |total_memory_usage_| and returns true.
+ //
+ // |current_size| is the up-to-date size of ByteStream of the Stream instance
+ // and |increase| must be the amount of data going to be added to the Stream
+ // instance.
+ bool UpdateMemoryUsage(const GURL& url, size_t current_size, size_t increase);
+
// Gets the stream associated with |url|. Returns NULL if there is no such
// stream.
scoped_refptr<Stream> GetStream(const GURL& url);
+ void set_max_memory_usage_for_testing(size_t size) {
+ max_memory_usage_ = size;
+ }
+
private:
typedef std::map<GURL, scoped_refptr<Stream> > StreamMap;
StreamMap streams_;
+ size_t total_memory_usage_;
+
+ // Maximum amount of memory allowed to use for Stream instances registered
+ // with this registry.
+ size_t max_memory_usage_;
+
DISALLOW_COPY_AND_ASSIGN(StreamRegistry);
};
} // namespace content
#endif // CONTENT_BROWSER_STREAMS_STREAM_REGISTRY_H_
-
-
diff --git a/chromium/content/browser/streams/stream_unittest.cc b/chromium/content/browser/streams/stream_unittest.cc
index 36add1d649d..a2d959305fa 100644
--- a/chromium/content/browser/streams/stream_unittest.cc
+++ b/chromium/content/browser/streams/stream_unittest.cc
@@ -41,7 +41,7 @@ class StreamTest : public testing::Test {
class TestStreamReader : public StreamReadObserver {
public:
- TestStreamReader() : buffer_(new net::GrowableIOBuffer()) {
+ TestStreamReader() : buffer_(new net::GrowableIOBuffer()), completed_(false) {
}
virtual ~TestStreamReader() {}
@@ -50,8 +50,25 @@ class TestStreamReader : public StreamReadObserver {
scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
int bytes_read = 0;
- while (stream->ReadRawData(buffer.get(), kBufferSize, &bytes_read) ==
- Stream::STREAM_HAS_DATA) {
+ while (true) {
+ Stream::StreamState state =
+ stream->ReadRawData(buffer.get(), kBufferSize, &bytes_read);
+ switch (state) {
+ case Stream::STREAM_HAS_DATA:
+ // TODO(tyoshino): Move these expectations to the beginning of Read()
+ // method once Stream::Finalize() is fixed.
+ EXPECT_FALSE(completed_);
+ break;
+ case Stream::STREAM_COMPLETE:
+ completed_ = true;
+ return;
+ case Stream::STREAM_EMPTY:
+ EXPECT_FALSE(completed_);
+ return;
+ case Stream::STREAM_ABORTED:
+ EXPECT_FALSE(completed_);
+ return;
+ }
size_t old_capacity = buffer_->capacity();
buffer_->SetCapacity(old_capacity + bytes_read);
memcpy(buffer_->StartOfBuffer() + old_capacity,
@@ -65,8 +82,13 @@ class TestStreamReader : public StreamReadObserver {
scoped_refptr<net::GrowableIOBuffer> buffer() { return buffer_; }
+ bool completed() const {
+ return completed_;
+ }
+
private:
scoped_refptr<net::GrowableIOBuffer> buffer_;
+ bool completed_;
};
class TestStreamWriter : public StreamWriteObserver {
@@ -137,14 +159,38 @@ TEST_F(StreamTest, Stream) {
scoped_refptr<net::IOBuffer> buffer(NewIOBuffer(kBufferSize));
writer.Write(stream.get(), buffer, kBufferSize);
stream->Finalize();
- reader.Read(stream.get());
base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_TRUE(reader.completed());
ASSERT_EQ(reader.buffer()->capacity(), kBufferSize);
for (int i = 0; i < kBufferSize; i++)
EXPECT_EQ(buffer->data()[i], reader.buffer()->data()[i]);
}
+// Test that even if a reader receives an empty buffer, once TransferData()
+// method is called on it with |source_complete| = true, following Read() calls
+// on it never returns STREAM_EMPTY. Together with StreamTest.Stream above, this
+// guarantees that Reader::Read() call returns only STREAM_HAS_DATA
+// or STREAM_COMPLETE in |data_available_callback_| call corresponding to
+// Writer::Close().
+TEST_F(StreamTest, ClosedReaderDoesNotReturnStreamEmpty) {
+ TestStreamReader reader;
+ TestStreamWriter writer;
+
+ GURL url("blob://stream");
+ scoped_refptr<Stream> stream(
+ new Stream(registry_.get(), &writer, url));
+ EXPECT_TRUE(stream->SetReadObserver(&reader));
+
+ const int kBufferSize = 0;
+ scoped_refptr<net::IOBuffer> buffer(NewIOBuffer(kBufferSize));
+ stream->AddData(buffer, kBufferSize);
+ stream->Finalize();
+ base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_TRUE(reader.completed());
+ EXPECT_EQ(0, reader.buffer()->capacity());
+}
+
TEST_F(StreamTest, GetStream) {
TestStreamWriter writer;
@@ -207,4 +253,59 @@ TEST_F(StreamTest, UnregisterStream) {
ASSERT_FALSE(stream2.get());
}
+TEST_F(StreamTest, MemoryExceedMemoryUsageLimit) {
+ TestStreamWriter writer1;
+ TestStreamWriter writer2;
+
+ GURL url1("blob://stream");
+ scoped_refptr<Stream> stream1(
+ new Stream(registry_.get(), &writer1, url1));
+
+ GURL url2("blob://stream2");
+ scoped_refptr<Stream> stream2(
+ new Stream(registry_.get(), &writer2, url2));
+
+ const int kMaxMemoryUsage = 1500000;
+ registry_->set_max_memory_usage_for_testing(kMaxMemoryUsage);
+
+ const int kBufferSize = 1000000;
+ scoped_refptr<net::IOBuffer> buffer(NewIOBuffer(kBufferSize));
+ writer1.Write(stream1.get(), buffer, kBufferSize);
+ // Make transfer happen.
+ base::MessageLoop::current()->RunUntilIdle();
+
+ writer2.Write(stream2.get(), buffer, kBufferSize);
+
+ // Written data (1000000 * 2) exceeded limit (1500000). |stream2| should be
+ // unregistered with |registry_|.
+ EXPECT_EQ(NULL, registry_->GetStream(url2).get());
+
+ writer1.Write(stream1.get(), buffer, kMaxMemoryUsage - kBufferSize);
+ // Should be accepted since stream2 is unregistered and the new data is not
+ // so big to exceed the limit.
+ EXPECT_FALSE(registry_->GetStream(url1).get() == NULL);
+}
+
+TEST_F(StreamTest, UnderMemoryUsageLimit) {
+ TestStreamWriter writer;
+ TestStreamReader reader;
+
+ GURL url("blob://stream");
+ scoped_refptr<Stream> stream(new Stream(registry_.get(), &writer, url));
+ EXPECT_TRUE(stream->SetReadObserver(&reader));
+
+ registry_->set_max_memory_usage_for_testing(1500000);
+
+ const int kBufferSize = 1000000;
+ scoped_refptr<net::IOBuffer> buffer(NewIOBuffer(kBufferSize));
+ writer.Write(stream.get(), buffer, kBufferSize);
+
+ // Run loop to make |reader| consume the data.
+ base::MessageLoop::current()->RunUntilIdle();
+
+ writer.Write(stream.get(), buffer, kBufferSize);
+
+ EXPECT_EQ(stream.get(), registry_->GetStream(url).get());
+}
+
} // namespace content
diff --git a/chromium/content/browser/streams/stream_url_request_job.cc b/chromium/content/browser/streams/stream_url_request_job.cc
index e36c5d49ae6..09b9e6d7815 100644
--- a/chromium/content/browser/streams/stream_url_request_job.cc
+++ b/chromium/content/browser/streams/stream_url_request_job.cc
@@ -39,19 +39,42 @@ StreamURLRequestJob::~StreamURLRequestJob() {
void StreamURLRequestJob::OnDataAvailable(Stream* stream) {
// Clear the IO_PENDING status.
SetStatus(net::URLRequestStatus());
- if (pending_buffer_.get()) {
- int bytes_read;
- stream_->ReadRawData(
- pending_buffer_.get(), pending_buffer_size_, &bytes_read);
-
- // Clear the buffers before notifying the read is complete, so that it is
- // safe for the observer to read.
- pending_buffer_ = NULL;
- pending_buffer_size_ = 0;
-
- total_bytes_read_ += bytes_read;
- NotifyReadComplete(bytes_read);
+ // Do nothing if pending_buffer_ is empty, i.e. there's no ReadRawData()
+ // operation waiting for IO completion.
+ if (!pending_buffer_.get())
+ return;
+
+ // pending_buffer_ is set to the IOBuffer instance provided to ReadRawData()
+ // by URLRequestJob.
+
+ int bytes_read;
+ switch (stream_->ReadRawData(
+ pending_buffer_.get(), pending_buffer_size_, &bytes_read)) {
+ case Stream::STREAM_HAS_DATA:
+ DCHECK_GT(bytes_read, 0);
+ break;
+ case Stream::STREAM_COMPLETE:
+ // Ensure this. Calling NotifyReadComplete call with 0 signals
+ // completion.
+ bytes_read = 0;
+ break;
+ case Stream::STREAM_EMPTY:
+ NOTREACHED();
+ break;
+ case Stream::STREAM_ABORTED:
+ // Handle this as connection reset.
+ NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+ net::ERR_CONNECTION_RESET));
+ break;
}
+
+ // Clear the buffers before notifying the read is complete, so that it is
+ // safe for the observer to read.
+ pending_buffer_ = NULL;
+ pending_buffer_size_ = 0;
+
+ total_bytes_read_ += bytes_read;
+ NotifyReadComplete(bytes_read);
}
// net::URLRequestJob methods.
@@ -74,6 +97,7 @@ bool StreamURLRequestJob::ReadRawData(net::IOBuffer* buf,
if (request_failed_)
return true;
+ DCHECK(buf);
DCHECK(bytes_read);
int to_read = buf_size;
if (max_range_ && to_read) {
@@ -96,6 +120,11 @@ bool StreamURLRequestJob::ReadRawData(net::IOBuffer* buf,
pending_buffer_size_ = to_read;
SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
return false;
+ case Stream::STREAM_ABORTED:
+ // Handle this as connection reset.
+ NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+ net::ERR_CONNECTION_RESET));
+ return false;
}
NOTREACHED();
return false;
@@ -167,7 +196,6 @@ void StreamURLRequestJob::NotifyFailure(int error_code) {
// TODO(zork): Share these with BlobURLRequestJob.
net::HttpStatusCode status_code = net::HTTP_INTERNAL_SERVER_ERROR;
- std::string status_txt;
switch (error_code) {
case net::ERR_ACCESS_DENIED:
status_code = net::HTTP_FORBIDDEN;
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 4bb1798b514..8914fe5c50c 100644
--- a/chromium/content/browser/streams/stream_url_request_job_unittest.cc
+++ b/chromium/content/browser/streams/stream_url_request_job_unittest.cc
@@ -83,6 +83,7 @@ class StreamURLRequestJobTest : public testing::Test {
// Verify response.
EXPECT_TRUE(request_->status().is_success());
+ ASSERT_TRUE(request_->response_headers());
EXPECT_EQ(expected_status_code,
request_->response_headers()->response_code());
EXPECT_EQ(expected_response, delegate.data_received());
diff --git a/chromium/content/browser/tracing/OWNERS b/chromium/content/browser/tracing/OWNERS
index 93d1471e1ef..9130707df06 100644
--- a/chromium/content/browser/tracing/OWNERS
+++ b/chromium/content/browser/tracing/OWNERS
@@ -1 +1,2 @@
nduca@chromium.org
+dsinclair@chromium.org
diff --git a/chromium/content/browser/tracing/trace_controller_impl.cc b/chromium/content/browser/tracing/trace_controller_impl.cc
index 54e0c86cb42..fe08639876d 100644
--- a/chromium/content/browser/tracing/trace_controller_impl.cc
+++ b/chromium/content/browser/tracing/trace_controller_impl.cc
@@ -26,9 +26,11 @@ base::LazyInstance<TraceControllerImpl>::Leaky g_controller =
class AutoStopTraceSubscriberStdio : public TraceSubscriberStdio {
public:
AutoStopTraceSubscriberStdio(const base::FilePath& file_path)
- : TraceSubscriberStdio(file_path) {}
+ : TraceSubscriberStdio(file_path,
+ FILE_TYPE_PROPERTY_LIST,
+ false) {}
- static void EndStartupTrace(TraceSubscriberStdio* subscriber) {
+ static void EndStartupTrace(AutoStopTraceSubscriberStdio* subscriber) {
if (!TraceControllerImpl::GetInstance()->EndTracingAsync(subscriber))
delete subscriber;
// else, the tracing will end asynchronously in OnEndTracingComplete().
@@ -146,6 +148,10 @@ bool TraceControllerImpl::EndTracingAsync(TraceSubscriber* subscriber) {
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
@@ -299,20 +305,20 @@ void TraceControllerImpl::OnEndTracingAck(
if (pending_end_ack_count_ == 0)
return;
- if (--pending_end_ack_count_ == 0) {
- // All acks have been received.
- is_tracing_ = false;
-
- // Disable local trace.
- TraceLog::GetInstance()->SetDisabled();
- // During this call, our OnTraceDataCollected will be
- // called with the last of the local trace data. Since we are on the UI
- // thread, the call to OnTraceDataCollected will be synchronous, so we can
- // immediately call OnEndTracingComplete below.
+ 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::OnTraceDataCollected,
+ 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_) {
@@ -326,16 +332,6 @@ void TraceControllerImpl::OnEndTracingAck(
is_get_category_groups_ = false;
}
-
- if (pending_end_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.
- 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));
- }
}
void TraceControllerImpl::OnTraceDataCollected(
@@ -354,6 +350,20 @@ void TraceControllerImpl::OnTraceDataCollected(
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.
diff --git a/chromium/content/browser/tracing/trace_controller_impl.h b/chromium/content/browser/tracing/trace_controller_impl.h
index f24d283a125..6f2ccb5d481 100644
--- a/chromium/content/browser/tracing/trace_controller_impl.h
+++ b/chromium/content/browser/tracing/trace_controller_impl.h
@@ -81,6 +81,11 @@ class TraceControllerImpl : public TraceController {
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:
diff --git a/chromium/content/browser/tracing/trace_message_filter.h b/chromium/content/browser/tracing/trace_message_filter.h
index 8da34534604..41fd017827f 100644
--- a/chromium/content/browser/tracing/trace_message_filter.h
+++ b/chromium/content/browser/tracing/trace_message_filter.h
@@ -14,7 +14,7 @@
namespace content {
// This class sends and receives trace messages on the browser process.
-// See also: trace_controller.h
+// See also: tracing_controller.h
// See also: child_trace_message_filter.h
class TraceMessageFilter : public BrowserMessageFilter {
public:
diff --git a/chromium/content/browser/tracing/trace_subscriber_stdio.cc b/chromium/content/browser/tracing/trace_subscriber_stdio.cc
index b5f6e828c60..2c6aede56ce 100644
--- a/chromium/content/browser/tracing/trace_subscriber_stdio.cc
+++ b/chromium/content/browser/tracing/trace_subscriber_stdio.cc
@@ -14,39 +14,79 @@
namespace content {
// All method calls on this class are done on a SequencedWorkerPool thread.
-class TraceSubscriberStdioImpl
- : public base::RefCountedThreadSafe<TraceSubscriberStdioImpl> {
+class TraceSubscriberStdio::TraceSubscriberStdioWorker
+ : public base::RefCountedThreadSafe<TraceSubscriberStdioWorker> {
public:
- explicit TraceSubscriberStdioImpl(const base::FilePath& path)
+ TraceSubscriberStdioWorker(const base::FilePath& path,
+ FileType file_type,
+ bool has_system_trace)
: path_(path),
- file_(0) {}
-
- void OnStart() {
+ 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_);
- trace_buffer_.SetOutputCallback(
- base::Bind(&TraceSubscriberStdioImpl::Write, this));
file_ = file_util::OpenFile(path_, "w+");
- if (IsValid()) {
- LOG(INFO) << "Logging performance trace to file: " << path_.value();
- trace_buffer_.Start();
- } else {
+ 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 OnData(const scoped_refptr<base::RefCountedString>& data_ptr) {
- trace_buffer_.AddFragment(data_ptr->data());
+ 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 OnEnd() {
- trace_buffer_.Finish();
- CloseFile();
+ 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<TraceSubscriberStdioImpl>;
+ friend class base::RefCountedThreadSafe<TraceSubscriberStdioWorker>;
- ~TraceSubscriberStdioImpl() {
+ ~TraceSubscriberStdioWorker() {
CloseFile();
}
@@ -58,32 +98,79 @@ class TraceSubscriberStdioImpl
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);
}
- // This is important, as it breaks a reference cycle.
- trace_buffer_.SetOutputCallback(
- base::debug::TraceResultBuffer::OutputCallback());
+ WriteChars(chars + old_index, data.size() - old_index);
+ WriteString("\"");
+ wrote_system_trace_ = true;
}
- void Write(const std::string& output_str) {
+ void WriteChars(const char* output_chars, size_t size) {
+ if (size == 0)
+ return;
+
if (IsValid()) {
- size_t written = fwrite(output_str.data(), 1, output_str.size(), file_);
- if (written != output_str.size()) {
+ 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_;
- base::debug::TraceResultBuffer trace_buffer_;
+ 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)
- : impl_(new TraceSubscriberStdioImpl(path)) {
+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(&TraceSubscriberStdioImpl::OnStart, impl_));
+ base::Bind(&TraceSubscriberStdioWorker::OnTraceStart, worker_));
}
TraceSubscriberStdio::~TraceSubscriberStdio() {
@@ -92,14 +179,23 @@ TraceSubscriberStdio::~TraceSubscriberStdio() {
void TraceSubscriberStdio::OnEndTracingComplete() {
BrowserThread::PostBlockingPoolSequencedTask(
__FILE__, FROM_HERE,
- base::Bind(&TraceSubscriberStdioImpl::OnEnd, impl_));
+ base::Bind(&TraceSubscriberStdioWorker::OnTraceEnd, worker_));
}
void TraceSubscriberStdio::OnTraceDataCollected(
const scoped_refptr<base::RefCountedString>& data_ptr) {
BrowserThread::PostBlockingPoolSequencedTask(
__FILE__, FROM_HERE,
- base::Bind(&TraceSubscriberStdioImpl::OnData, impl_, data_ptr));
+ 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
index 06a70db8c88..b9fc4f74c19 100644
--- a/chromium/content/browser/tracing/trace_subscriber_stdio.h
+++ b/chromium/content/browser/tracing/trace_subscriber_stdio.h
@@ -17,14 +17,24 @@ class FilePath;
namespace content {
-class TraceSubscriberStdioImpl;
-
// Stdio implementation of TraceSubscriber. Use this to write traces to a file.
class CONTENT_EXPORT TraceSubscriberStdio
: NON_EXPORTED_BASE(public TraceSubscriber) {
public:
- // Creates or overwrites the specified file. Check IsValid() for success.
- explicit TraceSubscriberStdio(const base::FilePath& path);
+ 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
@@ -32,8 +42,13 @@ class CONTENT_EXPORT TraceSubscriberStdio
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:
- scoped_refptr<TraceSubscriberStdioImpl> impl_;
+ class TraceSubscriberStdioWorker;
+ scoped_refptr<TraceSubscriberStdioWorker> worker_;
DISALLOW_COPY_AND_ASSIGN(TraceSubscriberStdio);
};
diff --git a/chromium/content/browser/tracing/trace_subscriber_stdio_unittest.cc b/chromium/content/browser/tracing/trace_subscriber_stdio_unittest.cc
index 0b0e7c2ee80..10e51a968df 100644
--- a/chromium/content/browser/tracing/trace_subscriber_stdio_unittest.cc
+++ b/chromium/content/browser/tracing/trace_subscriber_stdio_unittest.cc
@@ -14,12 +14,14 @@ namespace content {
class TraceSubscriberStdioTest : public ::testing::Test {};
-TEST_F(TraceSubscriberStdioTest, CanWriteDataToFile) {
+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 subscriber(trace_file,
+ TraceSubscriberStdio::FILE_TYPE_ARRAY,
+ false);
std::string foo("foo");
subscriber.OnTraceDataCollected(
@@ -33,8 +35,98 @@ TEST_F(TraceSubscriberStdioTest, CanWriteDataToFile) {
}
BrowserThread::GetBlockingPool()->FlushForTesting();
std::string result;
- EXPECT_TRUE(file_util::ReadFileToString(trace_file, &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
new file mode 100644
index 00000000000..c88932e0597
--- /dev/null
+++ b/chromium/content/browser/tracing/tracing_controller_browsertest.cc
@@ -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.
+
+#include "base/file_util.h"
+#include "base/run_loop.h"
+#include "content/browser/tracing/tracing_controller_impl.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 {
+
+class TracingControllerTest : public ContentBrowserTest {
+ public:
+ TracingControllerTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ get_categories_done_callback_count_ = 0;
+ enable_recording_done_callback_count_ = 0;
+ disable_recording_done_callback_count_ = 0;
+ ContentBrowserTest::SetUp();
+ }
+
+ virtual void TearDown() OVERRIDE {
+ ContentBrowserTest::TearDown();
+ }
+
+ void Navigate(Shell* shell) {
+ NavigateToURL(shell, GetTestUrl("", "title.html"));
+ }
+
+ void GetCategoriesDoneCallbackTest(base::Closure quit_callback,
+ const std::set<std::string>& categories) {
+ get_categories_done_callback_count_++;
+ EXPECT_TRUE(categories.size() > 0);
+ quit_callback.Run();
+ }
+
+ void EnableRecordingDoneCallbackTest(base::Closure quit_callback) {
+ enable_recording_done_callback_count_++;
+ quit_callback.Run();
+ }
+
+ void DisableRecordingDoneCallbackTest(base::Closure quit_callback,
+ scoped_ptr<base::FilePath> file_path) {
+ disable_recording_done_callback_count_++;
+ EXPECT_TRUE(PathExists(*file_path));
+ quit_callback.Run();
+ }
+
+ int get_categories_done_callback_count() const {
+ return get_categories_done_callback_count_;
+ }
+
+ int enable_recording_done_callback_count() const {
+ return enable_recording_done_callback_count_;
+ }
+
+ int disable_recording_done_callback_count() const {
+ return disable_recording_done_callback_count_;
+ }
+
+ private:
+ int get_categories_done_callback_count_;
+ int enable_recording_done_callback_count_;
+ int disable_recording_done_callback_count_;
+};
+
+IN_PROC_BROWSER_TEST_F(TracingControllerTest, GetCategories) {
+ Navigate(shell());
+
+ TracingController* controller = TracingController::GetInstance();
+
+ base::RunLoop run_loop;
+ TracingController::GetCategoriesDoneCallback callback =
+ base::Bind(&TracingControllerTest::GetCategoriesDoneCallbackTest,
+ base::Unretained(this),
+ run_loop.QuitClosure());
+ controller->GetCategories(callback);
+ run_loop.Run();
+ EXPECT_EQ(get_categories_done_callback_count(), 1);
+}
+
+IN_PROC_BROWSER_TEST_F(TracingControllerTest, EnableAndDisableRecording) {
+ Navigate(shell());
+
+ TracingController* controller = TracingController::GetInstance();
+
+ {
+ 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);
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/tracing/tracing_controller_impl.cc b/chromium/content/browser/tracing/tracing_controller_impl.cc
new file mode 100644
index 00000000000..1c1c43aabf9
--- /dev/null
+++ b/chromium/content/browser/tracing/tracing_controller_impl.cc
@@ -0,0 +1,270 @@
+// Copyright 2013 The Chromium Authors. All rights 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/tracing_controller_impl.h"
+
+#include "base/bind.h"
+#include "base/file_util.h"
+#include "base/json/string_escape.h"
+#include "base/strings/string_number_conversions.h"
+#include "content/browser/tracing/trace_message_filter.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<TracingControllerImpl>::Leaky g_controller =
+ LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
+TracingController* TracingController::GetInstance() {
+ return TracingControllerImpl::GetInstance();
+}
+
+TracingControllerImpl::TracingControllerImpl() :
+ pending_end_ack_count_(0),
+ is_recording_(false),
+ category_filter_(
+ base::debug::CategoryFilter::kDefaultCategoryFilterString) {
+}
+
+TracingControllerImpl::~TracingControllerImpl() {
+ // This is a Leaky instance.
+ NOTREACHED();
+}
+
+TracingControllerImpl* TracingControllerImpl::GetInstance() {
+ return g_controller.Pointer();
+}
+
+void TracingControllerImpl::GetCategories(
+ const GetCategoriesDoneCallback& callback) {
+ 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.
+ pending_get_categories_done_callback_ = callback;
+ EnableRecording(base::debug::CategoryFilter("*"),
+ TracingController::Options(),
+ EnableRecordingDoneCallback());
+ DisableRecording(TracingFileResultCallback());
+}
+
+void TracingControllerImpl::EnableRecording(
+ const base::debug::CategoryFilter& 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_);
+
+ 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_);
+ }
+
+ if (!callback.is_null())
+ callback.Run();
+}
+
+void TracingControllerImpl::DisableRecording(
+ const TracingFileResultCallback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ if (!can_end_recording())
+ return;
+
+ pending_disable_recording_done_callback_ = callback;
+
+ // Disable local trace early to avoid traces during end-tracing process from
+ // 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));
+ }
+
+ // 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;
+
+ // 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(&TracingControllerImpl::OnDisableRecordingAcked,
+ base::Unretained(this), category_groups));
+ }
+
+ // Notify all child processes.
+ for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) {
+ it->get()->SendEndTracing();
+ }
+}
+
+void TracingControllerImpl::EnableMonitoring(
+ const base::debug::CategoryFilter& filter,
+ TracingController::Options options,
+ const EnableMonitoringDoneCallback& callback) {
+ NOTIMPLEMENTED();
+}
+
+void TracingControllerImpl::DisableMonitoring(
+ const DisableMonitoringDoneCallback& callback) {
+ NOTIMPLEMENTED();
+}
+
+void TracingControllerImpl::GetMonitoringStatus(
+ bool* out_enabled,
+ base::debug::CategoryFilter* out_filter,
+ TracingController::Options* out_options) {
+ NOTIMPLEMENTED();
+}
+
+void TracingControllerImpl::CaptureCurrentMonitoringSnapshot(
+ const TracingFileResultCallback& callback) {
+ NOTIMPLEMENTED();
+}
+
+void TracingControllerImpl::AddFilter(TraceMessageFilter* filter) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(&TracingControllerImpl::AddFilter, base::Unretained(this),
+ make_scoped_refptr(filter)));
+ return;
+ }
+
+ filters_.insert(filter);
+ if (is_recording_enabled()) {
+ std::string cf_str = category_filter_.ToString();
+ filter->SendBeginTracing(cf_str, trace_options_);
+ }
+}
+
+void TracingControllerImpl::RemoveFilter(TraceMessageFilter* filter) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(&TracingControllerImpl::RemoveFilter, base::Unretained(this),
+ make_scoped_refptr(filter)));
+ return;
+ }
+
+ filters_.erase(filter);
+}
+
+void TracingControllerImpl::OnDisableRecordingAcked(
+ const std::vector<std::string>& known_category_groups) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(&TracingControllerImpl::OnDisableRecordingAcked,
+ 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(&TracingControllerImpl::OnLocalTraceDataCollected,
+ base::Unretained(this)));
+ }
+
+ if (pending_end_ack_count_ != 0)
+ return;
+
+ // All acks (including from the subprocesses and the local trace) have been
+ // received.
+ is_recording_ = false;
+
+ // Trigger callback if one is set.
+ 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();
+ }
+}
+
+void TracingControllerImpl::OnEndTracingComplete() {
+ if (pending_disable_recording_done_callback_.is_null())
+ return;
+
+ pending_disable_recording_done_callback_.Run(recording_result_file_.Pass());
+ pending_disable_recording_done_callback_.Reset();
+}
+
+void TracingControllerImpl::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(&TracingControllerImpl::OnTraceDataCollected,
+ base::Unretained(this), events_str_ptr));
+ 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);
+
+ // 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(",");
+
+ file_util::WriteFile(*recording_result_file_,
+ javascript.c_str(), javascript.length());
+}
+
+void TracingControllerImpl::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)
+ return;
+
+ // Simulate an DisableRecordingAcked for the local trace.
+ std::vector<std::string> category_groups;
+ TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups);
+ OnDisableRecordingAcked(category_groups);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/tracing/tracing_controller_impl.h b/chromium/content/browser/tracing/tracing_controller_impl.h
new file mode 100644
index 00000000000..22192255444
--- /dev/null
+++ b/chromium/content/browser/tracing/tracing_controller_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_TRACING_TRACING_CONTROLLER_IMPL_H_
+#define CONTENT_BROWSER_TRACING_TRACING_CONTROLLER_IMPL_H_
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/lazy_instance.h"
+#include "content/public/browser/trace_subscriber.h"
+#include "content/public/browser/tracing_controller.h"
+
+namespace content {
+
+class TraceMessageFilter;
+
+class TracingControllerImpl :
+ public TracingController, public TraceSubscriber {
+ public:
+ static TracingControllerImpl* GetInstance();
+
+ // TracingController implementation.
+ virtual void GetCategories(
+ const GetCategoriesDoneCallback& callback) OVERRIDE;
+ virtual void EnableRecording(
+ const base::debug::CategoryFilter& filter,
+ TracingController::Options options,
+ const EnableRecordingDoneCallback& callback) OVERRIDE;
+ virtual void DisableRecording(
+ const TracingFileResultCallback& callback) OVERRIDE;
+ virtual void EnableMonitoring(const base::debug::CategoryFilter& filter,
+ TracingController::Options options,
+ const EnableMonitoringDoneCallback& callback) OVERRIDE;
+ virtual void DisableMonitoring(
+ const DisableMonitoringDoneCallback& callback) OVERRIDE;
+ virtual void GetMonitoringStatus(
+ bool* out_enabled,
+ base::debug::CategoryFilter* out_filter,
+ TracingController::Options* out_options) OVERRIDE;
+ virtual void CaptureCurrentMonitoringSnapshot(
+ const TracingFileResultCallback& callback) OVERRIDE;
+
+ private:
+ typedef std::set<scoped_refptr<TraceMessageFilter> > FilterMap;
+
+ friend struct base::DefaultLazyInstanceTraits<TracingControllerImpl>;
+ friend class TraceMessageFilter;
+
+ 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 is_recording_enabled() const {
+ return can_end_recording();
+ }
+
+ // Methods for use by TraceMessageFilter.
+ void AddFilter(TraceMessageFilter* filter);
+ void RemoveFilter(TraceMessageFilter* filter);
+
+ // Callback of TraceLog::Flush() for the local trace.
+ void OnLocalTraceDataCollected(
+ const scoped_refptr<base::RefCountedString>& events_str_ptr,
+ bool has_more_events);
+
+ void OnDisableRecordingAcked(
+ const std::vector<std::string>& known_category_groups);
+
+ FilterMap filters_;
+ // Pending acks for DisableRecording.
+ int pending_end_ack_count_;
+ bool is_recording_;
+ 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_;
+
+ DISALLOW_COPY_AND_ASSIGN(TracingControllerImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_TRACING_TRACING_CONTROLLER_IMPL_H_
diff --git a/chromium/content/browser/tracing/tracing_ui.cc b/chromium/content/browser/tracing/tracing_ui.cc
index aab652d5bf1..15bd2cf2590 100644
--- a/chromium/content/browser/tracing/tracing_ui.cc
+++ b/chromium/content/browser/tracing/tracing_ui.cc
@@ -13,6 +13,7 @@
#include "base/file_util.h"
#include "base/json/string_escape.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"
@@ -225,7 +226,7 @@ void TracingMessageHandler::OnBeginRequestBufferPercentFull(
// TaskProxy callback when reading is complete.
void ReadTraceFileCallback(TaskProxy* proxy, const base::FilePath& path) {
std::string file_contents;
- if (!file_util::ReadFileToString(path, &file_contents))
+ if (!base::ReadFileToString(path, &file_contents))
return;
// We need to escape the file contents, because it will go into a javascript
@@ -269,7 +270,8 @@ void ReadTraceFileCallback(TaskProxy* proxy, const base::FilePath& path) {
void WriteTraceFileCallback(TaskProxy* proxy,
const base::FilePath& path,
std::string* contents) {
- if (!file_util::WriteFile(path, contents->c_str(), contents->size()))
+ int size = base::checked_numeric_cast<int>(contents->size());
+ if (file_util::WriteFile(path, contents->c_str(), size) != size)
return;
BrowserThread::PostTask(
@@ -363,7 +365,7 @@ void TracingMessageHandler::OnSaveTraceFile(const base::ListValue* list) {
if (select_trace_file_dialog_.get())
return;
- DCHECK(list->GetSize() == 1);
+ DCHECK_EQ(1U, list->GetSize());
std::string* trace_data = new std::string();
bool ok = list->GetString(0, trace_data);
diff --git a/chromium/content/browser/utility_process_host_impl.cc b/chromium/content/browser/utility_process_host_impl.cc
index 2e562188d24..f2b3bc31dee 100644
--- a/chromium/content/browser/utility_process_host_impl.cc
+++ b/chromium/content/browser/utility_process_host_impl.cc
@@ -16,7 +16,6 @@
#include "base/synchronization/waitable_event.h"
#include "content/browser/browser_child_process_host_impl.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
-#include "content/child/child_process.h"
#include "content/common/child_process_host_impl.h"
#include "content/common/utility_messages.h"
#include "content/public/browser/browser_thread.h"
@@ -24,7 +23,6 @@
#include "content/public/browser/utility_process_host_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/process_type.h"
-#include "content/utility/utility_thread_impl.h"
#include "ipc/ipc_switches.h"
#include "ui/base/ui_base_switches.h"
@@ -53,53 +51,8 @@ private:
};
#endif
-// We want to ensure there's only one utility thread running at a time, as there
-// are many globals used in the utility process.
-static base::LazyInstance<base::Lock> g_one_utility_thread_lock;
-// Single process not supported in multiple dll mode currently.
-#if !defined(CHROME_MULTIPLE_DLL)
-class UtilityMainThread : public base::Thread {
- public:
- UtilityMainThread(const std::string& channel_id)
- : Thread("Chrome_InProcUtilityThread"),
- channel_id_(channel_id) {
- }
-
- virtual ~UtilityMainThread() {
- Stop();
- }
-
- private:
- // base::Thread implementation:
- virtual void Init() OVERRIDE {
- // We need to return right away or else the main thread that started us will
- // hang.
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&UtilityMainThread::InitInternal, base::Unretained(this)));
- }
-
- virtual void CleanUp() OVERRIDE {
- child_process_.reset();
-
- // See comment in RendererMainThread.
- SetThreadWasQuitProperly(true);
- g_one_utility_thread_lock.Get().Release();
- }
-
- void InitInternal() {
- g_one_utility_thread_lock.Get().Acquire();
- child_process_.reset(new ChildProcess());
- child_process_->set_main_thread(new UtilityThreadImpl(channel_id_));
- }
-
- std::string channel_id_;
- scoped_ptr<ChildProcess> child_process_;
-
- DISALLOW_COPY_AND_ASSIGN(UtilityMainThread);
-};
-#endif // !CHROME_MULTIPLE_DLL
+UtilityMainThreadFactoryFunction g_utility_main_thread_factory = NULL;
UtilityProcessHost* UtilityProcessHost::Create(
UtilityProcessHostClient* client,
@@ -107,6 +60,11 @@ UtilityProcessHost* UtilityProcessHost::Create(
return new UtilityProcessHostImpl(client, client_task_runner);
}
+void UtilityProcessHost::RegisterUtilityMainThreadFactory(
+ UtilityMainThreadFactoryFunction create) {
+ g_utility_main_thread_factory = create;
+}
+
UtilityProcessHostImpl::UtilityProcessHostImpl(
UtilityProcessHostClient* client,
base::SequencedTaskRunner* client_task_runner)
@@ -172,7 +130,7 @@ const ChildProcessData& UtilityProcessHostImpl::GetData() {
#if defined(OS_POSIX)
-void UtilityProcessHostImpl::SetEnv(const base::EnvironmentVector& env) {
+void UtilityProcessHostImpl::SetEnv(const base::EnvironmentMap& env) {
env_ = env;
}
@@ -196,15 +154,13 @@ bool UtilityProcessHostImpl::StartProcess() {
return false;
// Single process not supported in multiple dll mode currently.
-#if !defined(CHROME_MULTIPLE_DLL)
- if (RenderProcessHost::run_renderer_in_process()) {
+ if (RenderProcessHost::run_renderer_in_process() &&
+ 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(new UtilityMainThread(channel_id));
+ in_process_thread_.reset(g_utility_main_thread_factory(channel_id));
in_process_thread_->Start();
- } else
-#endif // !CHROME_MULTIPLE_DLL
- {
+ } else {
const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
int child_flags = child_flags_;
@@ -247,13 +203,14 @@ bool UtilityProcessHostImpl::StartProcess() {
// 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 (usually "xterm -e gdb
- // --args").
+ // 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_);
+ cmd_line->AppendSwitchPath(switches::kUtilityProcessAllowedDir,
+ exposed_dir_);
#endif
if (is_mdns_enabled_)
diff --git a/chromium/content/browser/utility_process_host_impl.h b/chromium/content/browser/utility_process_host_impl.h
index 6eecd3d8985..039e20f8c50 100644
--- a/chromium/content/browser/utility_process_host_impl.h
+++ b/chromium/content/browser/utility_process_host_impl.h
@@ -10,6 +10,7 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
+#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
@@ -18,11 +19,11 @@
namespace base {
class SequencedTaskRunner;
+class Thread;
}
namespace content {
class BrowserChildProcessHostImpl;
-class UtilityMainThread;
class CONTENT_EXPORT UtilityProcessHostImpl
: public NON_EXPORTED_BASE(UtilityProcessHost),
@@ -42,7 +43,7 @@ class CONTENT_EXPORT UtilityProcessHostImpl
virtual void EnableZygote() OVERRIDE;
virtual const ChildProcessData& GetData() OVERRIDE;
#if defined(OS_POSIX)
- virtual void SetEnv(const base::EnvironmentVector& env) OVERRIDE;
+ virtual void SetEnv(const base::EnvironmentMap& env) OVERRIDE;
#endif
void set_child_flags(int flags) { child_flags_ = flags; }
@@ -77,16 +78,14 @@ class CONTENT_EXPORT UtilityProcessHostImpl
// Launch the utility process from the zygote. Defaults to false.
bool use_linux_zygote_;
- base::EnvironmentVector env_;
+ base::EnvironmentMap env_;
bool started_;
scoped_ptr<BrowserChildProcessHostImpl> process_;
-#if !defined(CHROME_MULTIPLE_DLL)
// Used in single-process mode instead of process_.
- scoped_ptr<UtilityMainThread> in_process_thread_;
-#endif
+ scoped_ptr<base::Thread> in_process_thread_;
DISALLOW_COPY_AND_ASSIGN(UtilityProcessHostImpl);
};
diff --git a/chromium/content/browser/web_contents/aura/image_window_delegate.cc b/chromium/content/browser/web_contents/aura/image_window_delegate.cc
index 1829f46ba44..dbb066c894d 100644
--- a/chromium/content/browser/web_contents/aura/image_window_delegate.cc
+++ b/chromium/content/browser/web_contents/aura/image_window_delegate.cc
@@ -4,6 +4,7 @@
#include "content/browser/web_contents/aura/image_window_delegate.h"
+#include "ui/base/cursor/cursor.h"
#include "ui/base/hit_test.h"
#include "ui/compositor/compositor.h"
#include "ui/gfx/canvas.h"
@@ -93,8 +94,8 @@ bool ImageWindowDelegate::HasHitTestMask() const {
void ImageWindowDelegate::GetHitTestMask(gfx::Path* mask) const {
}
-scoped_refptr<ui::Texture> ImageWindowDelegate::CopyTexture() {
- return scoped_refptr<ui::Texture>();
+void ImageWindowDelegate::DidRecreateLayer(ui::Layer *old_layer,
+ ui::Layer *new_layer) {
}
} // namespace content
diff --git a/chromium/content/browser/web_contents/aura/image_window_delegate.h b/chromium/content/browser/web_contents/aura/image_window_delegate.h
index ad92ce28f91..561fac8a109 100644
--- a/chromium/content/browser/web_contents/aura/image_window_delegate.h
+++ b/chromium/content/browser/web_contents/aura/image_window_delegate.h
@@ -42,7 +42,8 @@ class ImageWindowDelegate : public aura::WindowDelegate {
virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE;
virtual bool HasHitTestMask() const OVERRIDE;
virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE;
- virtual scoped_refptr<ui::Texture> CopyTexture() OVERRIDE;
+ virtual void DidRecreateLayer(ui::Layer* old_layer,
+ ui::Layer* new_layer) OVERRIDE;
protected:
gfx::Image image_;
diff --git a/chromium/content/browser/web_contents/aura/window_slider.cc b/chromium/content/browser/web_contents/aura/window_slider.cc
index 7afd32dd3d7..c9c3797b54c 100644
--- a/chromium/content/browser/web_contents/aura/window_slider.cc
+++ b/chromium/content/browser/web_contents/aura/window_slider.cc
@@ -11,9 +11,9 @@
#include "content/browser/web_contents/aura/shadow_layer_delegate.h"
#include "content/public/browser/overscroll_configuration.h"
#include "ui/aura/window.h"
-#include "ui/base/events/event.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/events/event.h"
namespace content {
@@ -58,8 +58,11 @@ WindowSlider::WindowSlider(Delegate* delegate,
owner_(owner),
delta_x_(0.f),
weak_factory_(this),
- horiz_start_threshold_(content::GetOverscrollConfig(
- content::OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START)),
+ active_start_threshold_(0.f),
+ start_threshold_touchscreen_(content::GetOverscrollConfig(
+ content::OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN)),
+ start_threshold_touchpad_(content::GetOverscrollConfig(
+ content::OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHPAD)),
complete_threshold_(content::GetOverscrollConfig(
content::OVERSCROLL_CONFIG_HORIZ_THRESHOLD_COMPLETE)) {
event_window_->AddPreTargetHandler(this);
@@ -89,7 +92,7 @@ void WindowSlider::ChangeOwner(aura::Window* new_owner) {
}
bool WindowSlider::IsSlideInProgress() const {
- return fabs(delta_x_) >= horiz_start_threshold_ || slider_.get() ||
+ return fabs(delta_x_) >= active_start_threshold_ || slider_.get() ||
weak_factory_.HasWeakPtrs();
}
@@ -107,7 +110,7 @@ void WindowSlider::SetupSliderLayer() {
void WindowSlider::UpdateForScroll(float x_offset, float y_offset) {
float old_delta = delta_x_;
delta_x_ += x_offset;
- if (fabs(delta_x_) < horiz_start_threshold_ && !slider_.get())
+ if (fabs(delta_x_) < active_start_threshold_ && !slider_.get())
return;
if ((old_delta < 0 && delta_x_ > 0) ||
@@ -127,13 +130,13 @@ void WindowSlider::UpdateForScroll(float x_offset, float y_offset) {
SetupSliderLayer();
}
- if (delta_x_ <= -horiz_start_threshold_) {
+ if (delta_x_ <= -active_start_threshold_) {
translate = owner_->bounds().width() +
- std::max(delta_x_ + horiz_start_threshold_,
+ std::max(delta_x_ + active_start_threshold_,
static_cast<float>(-owner_->bounds().width()));
translate_layer = slider_.get();
- } else if (delta_x_ >= horiz_start_threshold_) {
- translate = std::min(delta_x_ - horiz_start_threshold_,
+ } else if (delta_x_ >= active_start_threshold_) {
+ translate = std::min(delta_x_ - active_start_threshold_,
static_cast<float>(owner_->bounds().width()));
translate_layer = owner_->layer();
} else {
@@ -153,7 +156,7 @@ void WindowSlider::UpdateForFling(float x_velocity, float y_velocity) {
return;
int width = owner_->bounds().width();
- float ratio = (fabs(delta_x_) - horiz_start_threshold_) / width;
+ float ratio = (fabs(delta_x_) - active_start_threshold_) / width;
if (ratio < complete_threshold_) {
ResetScroll();
return;
@@ -163,7 +166,7 @@ void WindowSlider::UpdateForFling(float x_velocity, float y_velocity) {
ui::ScopedLayerAnimationSettings settings(sliding->GetAnimator());
settings.SetPreemptionStrategy(
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
- settings.SetTweenType(ui::Tween::EASE_OUT);
+ settings.SetTweenType(gfx::Tween::EASE_OUT);
settings.AddObserver(new CallbackAnimationObserver(
base::Bind(&WindowSlider::CompleteWindowSlideAfterAnimation,
weak_factory_.GetWeakPtr())));
@@ -187,7 +190,7 @@ void WindowSlider::ResetScroll() {
ui::ScopedLayerAnimationSettings settings(layer->GetAnimator());
settings.SetPreemptionStrategy(
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
- settings.SetTweenType(ui::Tween::EASE_OUT);
+ settings.SetTweenType(gfx::Tween::EASE_OUT);
// Delete the layer and the shadow at the end of the animation.
settings.AddObserver(new CallbackAnimationObserver(
@@ -205,7 +208,7 @@ void WindowSlider::ResetScroll() {
ui::ScopedLayerAnimationSettings settings(owner_->layer()->GetAnimator());
settings.SetPreemptionStrategy(
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
- settings.SetTweenType(ui::Tween::EASE_OUT);
+ settings.SetTweenType(gfx::Tween::EASE_OUT);
settings.AddObserver(new CallbackAnimationObserver(
base::Bind(&WindowSlider::AbortWindowSlideAfterAnimation,
weak_factory_.GetWeakPtr())));
@@ -245,6 +248,7 @@ void WindowSlider::OnMouseEvent(ui::MouseEvent* event) {
}
void WindowSlider::OnScrollEvent(ui::ScrollEvent* event) {
+ active_start_threshold_ = start_threshold_touchpad_;
if (event->type() == ui::ET_SCROLL)
UpdateForScroll(event->x_offset_ordinal(), event->y_offset_ordinal());
else if (event->type() == ui::ET_SCROLL_FLING_START)
@@ -255,6 +259,7 @@ void WindowSlider::OnScrollEvent(ui::ScrollEvent* event) {
}
void WindowSlider::OnGestureEvent(ui::GestureEvent* event) {
+ active_start_threshold_ = start_threshold_touchscreen_;
const ui::GestureEventDetails& details = event->details();
switch (event->type()) {
case ui::ET_GESTURE_SCROLL_BEGIN:
diff --git a/chromium/content/browser/web_contents/aura/window_slider.h b/chromium/content/browser/web_contents/aura/window_slider.h
index 227ad1ba82c..7100bf5c475 100644
--- a/chromium/content/browser/web_contents/aura/window_slider.h
+++ b/chromium/content/browser/web_contents/aura/window_slider.h
@@ -10,7 +10,7 @@
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
#include "ui/aura/window_observer.h"
-#include "ui/base/events/event_handler.h"
+#include "ui/events/event_handler.h"
namespace ui {
class Layer;
@@ -120,7 +120,10 @@ class CONTENT_EXPORT WindowSlider : public ui::EventHandler,
base::WeakPtrFactory<WindowSlider> weak_factory_;
- const float horiz_start_threshold_;
+ float active_start_threshold_;
+
+ const float start_threshold_touchscreen_;
+ const float start_threshold_touchpad_;
const float complete_threshold_;
DISALLOW_COPY_AND_ASSIGN(WindowSlider);
diff --git a/chromium/content/browser/web_contents/interstitial_page_impl.cc b/chromium/content/browser/web_contents/interstitial_page_impl.cc
index 232217d368f..bb93dc3d6c9 100644
--- a/chromium/content/browser/web_contents/interstitial_page_impl.cc
+++ b/chromium/content/browser/web_contents/interstitial_page_impl.cc
@@ -244,7 +244,7 @@ void InterstitialPageImpl::Hide() {
RenderWidgetHostView* old_view =
web_contents_->GetRenderViewHost()->GetView();
if (web_contents_->GetInterstitialPage() == this &&
- old_view && !old_view->IsShowing()) {
+ old_view && !old_view->IsShowing() && !web_contents_->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
@@ -378,7 +378,8 @@ void InterstitialPageImpl::DidNavigate(
}
// The RenderViewHost has loaded its contents, we can show it now.
- render_view_host_->GetView()->Show();
+ if (!web_contents_->IsHidden())
+ render_view_host_->GetView()->Show();
web_contents_->AttachInterstitialPage(this);
RenderWidgetHostView* rwh_view =
@@ -503,6 +504,7 @@ RenderViewHost* InterstitialPageImpl::CreateRenderViewHost() {
this,
MSG_ROUTING_NONE,
MSG_ROUTING_NONE,
+ false,
false);
web_contents_->RenderViewForInterstitialPageCreated(render_view_host);
return render_view_host;
diff --git a/chromium/content/browser/web_contents/navigation_controller_impl.cc b/chromium/content/browser/web_contents/navigation_controller_impl.cc
index 2c0596d9c83..faad72b5f38 100644
--- a/chromium/content/browser/web_contents/navigation_controller_impl.cc
+++ b/chromium/content/browser/web_contents/navigation_controller_impl.cc
@@ -637,8 +637,8 @@ void NavigationControllerImpl::LoadURLWithParams(const LoadURLParams& params) {
case LOAD_TYPE_DEFAULT:
break;
case LOAD_TYPE_BROWSER_INITIATED_HTTP_POST:
- if (!params.url.SchemeIs(chrome::kHttpScheme) &&
- !params.url.SchemeIs(chrome::kHttpsScheme)) {
+ if (!params.url.SchemeIs(kHttpScheme) &&
+ !params.url.SchemeIs(kHttpsScheme)) {
NOTREACHED() << "Http post load must use http(s) scheme.";
return;
}
@@ -798,6 +798,7 @@ bool NavigationControllerImpl::RendererDidNavigate(
NavigationEntryImpl* active_entry =
NavigationEntryImpl::FromNavigationEntry(GetLastCommittedEntry());
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);
@@ -1415,6 +1416,10 @@ bool NavigationControllerImpl::NeedsReload() const {
return needs_reload_;
}
+void NavigationControllerImpl::SetNeedsReload() {
+ needs_reload_ = true;
+}
+
void NavigationControllerImpl::RemoveEntryAtIndexInternal(int index) {
DCHECK(index < GetEntryCount());
DCHECK(index != last_committed_entry_index_);
@@ -1557,21 +1562,18 @@ void NavigationControllerImpl::NavigateToPendingEntry(ReloadType reload_type) {
void NavigationControllerImpl::NotifyNavigationEntryCommitted(
LoadCommittedDetails* details) {
details->entry = GetActiveEntry();
- NotificationDetails notification_details =
- Details<LoadCommittedDetails>(details);
// 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(notification_details);
+ ssl_manager_.DidCommitProvisionalLoad(*details);
- // TODO(pkasting): http://b/1113079 Probably these explicit notification paths
- // should be removed, and interested parties should just listen for the
- // notification below instead.
web_contents_->NotifyNavigationStateChanged(kInvalidateAll);
-
web_contents_->NotifyNavigationEntryCommitted(*details);
+ // TODO(avi): Remove. http://crbug.com/170921
+ NotificationDetails notification_details =
+ Details<LoadCommittedDetails>(details);
NotificationService::current()->Notify(
NOTIFICATION_NAV_ENTRY_COMMITTED,
Source<NavigationController>(this),
diff --git a/chromium/content/browser/web_contents/navigation_controller_impl.h b/chromium/content/browser/web_contents/navigation_controller_impl.h
index 2f0d71ea966..6e6f333506c 100644
--- a/chromium/content/browser/web_contents/navigation_controller_impl.h
+++ b/chromium/content/browser/web_contents/navigation_controller_impl.h
@@ -77,6 +77,7 @@ class CONTENT_EXPORT NavigationControllerImpl
virtual void SetMaxRestoredPageID(int32 max_id) OVERRIDE;
virtual int32 GetMaxRestoredPageID() const OVERRIDE;
virtual bool NeedsReload() const OVERRIDE;
+ virtual void SetNeedsReload() OVERRIDE;
virtual void CancelPendingReload() OVERRIDE;
virtual void ContinuePendingReload() OVERRIDE;
virtual bool IsInitialNavigation() const OVERRIDE;
@@ -366,7 +367,7 @@ class CONTENT_EXPORT NavigationControllerImpl
// of the restored entries to update its max page ID.
int32 max_restored_page_id_;
- // Manages the SSL security UI
+ // Manages the SSL security UI.
SSLManager ssl_manager_;
// Whether we need to be reloaded when made active.
diff --git a/chromium/content/browser/web_contents/navigation_controller_impl_unittest.cc b/chromium/content/browser/web_contents/navigation_controller_impl_unittest.cc
index df6a47c1b13..e91ad13fe72 100644
--- a/chromium/content/browser/web_contents/navigation_controller_impl_unittest.cc
+++ b/chromium/content/browser/web_contents/navigation_controller_impl_unittest.cc
@@ -355,8 +355,9 @@ TEST_F(NavigationControllerTest, LoadURL) {
EXPECT_FALSE(controller.CanGoForward());
EXPECT_EQ(contents()->GetMaxPageID(), -1);
- // The timestamp should not have been set yet.
+ // Neither the timestamp nor the status code should have been set yet.
EXPECT_TRUE(controller.GetPendingEntry()->GetTimestamp().is_null());
+ EXPECT_EQ(0, controller.GetPendingEntry()->GetHttpStatusCode());
// We should have gotten no notifications from the preceeding checks.
EXPECT_EQ(0U, notifications.size());
@@ -2655,6 +2656,20 @@ TEST_F(NavigationControllerTest, RendererInitiatedPendingEntries) {
contents()->DidStartProvisionalLoadForFrame(
test_rvh(), 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);
+ NavigationEntryImpl::FromNavigationEntry(controller.GetPendingEntry())->
+ set_should_replace_entry(true);
+ contents()->DidStartProvisionalLoadForFrame(
+ test_rvh(), 1, -1, true, url2);
+ EXPECT_TRUE(
+ NavigationEntryImpl::FromNavigationEntry(controller.GetPendingEntry())->
+ should_replace_entry());
+ test_rvh()->SendNavigate(0, url2);
+ EXPECT_EQ(url2, controller.GetLastCommittedEntry()->GetURL());
}
// Tests that the URLs for renderer-initiated navigations are not displayed to
@@ -2912,6 +2927,23 @@ TEST_F(NavigationControllerTest, CloneOmitsInterstitials) {
ASSERT_EQ(2, clone->GetController().GetEntryCount());
}
+// Test requesting and triggering a lazy reload.
+TEST_F(NavigationControllerTest, LazyReload) {
+ NavigationControllerImpl& controller = controller_impl();
+ const GURL url("http://foo");
+ NavigateAndCommit(url);
+ ASSERT_FALSE(controller.NeedsReload());
+
+ // Request a reload to happen when the controller becomes active (e.g. after
+ // the renderer gets killed in background on Android).
+ controller.SetNeedsReload();
+ ASSERT_TRUE(controller.NeedsReload());
+
+ // Set the controller as active, triggering the requested reload.
+ controller.SetActive(true);
+ ASSERT_FALSE(controller.NeedsReload());
+}
+
// Tests a subframe navigation while a toplevel navigation is pending.
// http://crbug.com/43967
TEST_F(NavigationControllerTest, SubframeWhilePending) {
diff --git a/chromium/content/browser/web_contents/navigation_entry_impl.cc b/chromium/content/browser/web_contents/navigation_entry_impl.cc
index a23b7b6623a..10d50ca0df2 100644
--- a/chromium/content/browser/web_contents/navigation_entry_impl.cc
+++ b/chromium/content/browser/web_contents/navigation_entry_impl.cc
@@ -10,7 +10,7 @@
#include "content/public/common/content_constants.h"
#include "content/public/common/url_constants.h"
#include "net/base/net_util.h"
-#include "ui/base/text/text_elider.h"
+#include "ui/gfx/text_elider.h"
// Use this to get a new unique ID for a NavigationEntry during construction.
// The returned ID is guaranteed to be nonzero (which is the "no ID" indicator).
@@ -48,6 +48,7 @@ NavigationEntryImpl::NavigationEntryImpl()
post_id_(-1),
restore_type_(RESTORE_NONE),
is_overriding_user_agent_(false),
+ http_status_code_(0),
is_renderer_initiated_(false),
should_replace_entry_(false),
should_clear_history_list_(false),
@@ -75,6 +76,7 @@ NavigationEntryImpl::NavigationEntryImpl(SiteInstanceImpl* instance,
post_id_(-1),
restore_type_(RESTORE_NONE),
is_overriding_user_agent_(false),
+ http_status_code_(0),
is_renderer_initiated_(is_renderer_initiated),
should_replace_entry_(false),
should_clear_history_list_(false),
@@ -189,7 +191,7 @@ const string16& NavigationEntryImpl::GetTitleForDisplay(
title = title.substr(slashpos + 1);
}
- ui::ElideString(title, kMaxTitleChars, &cached_display_title_);
+ gfx::ElideString(title, kMaxTitleChars, &cached_display_title_);
return cached_display_title_;
}
@@ -277,6 +279,14 @@ base::Time NavigationEntryImpl::GetTimestamp() const {
return timestamp_;
}
+void NavigationEntryImpl::SetHttpStatusCode(int http_status_code) {
+ http_status_code_ = http_status_code;
+}
+
+int NavigationEntryImpl::GetHttpStatusCode() const {
+ return http_status_code_;
+}
+
void NavigationEntryImpl::SetCanLoadLocalResources(bool allow) {
can_load_local_resources_ = allow;
}
diff --git a/chromium/content/browser/web_contents/navigation_entry_impl.h b/chromium/content/browser/web_contents/navigation_entry_impl.h
index 96d7ac9e2ba..63924b8ad73 100644
--- a/chromium/content/browser/web_contents/navigation_entry_impl.h
+++ b/chromium/content/browser/web_contents/navigation_entry_impl.h
@@ -84,6 +84,8 @@ class CONTENT_EXPORT NavigationEntryImpl
virtual bool GetExtraData(const std::string& key,
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;
void set_unique_id(int unique_id) {
unique_id_ = unique_id;
@@ -231,6 +233,7 @@ class CONTENT_EXPORT NavigationEntryImpl
GURL original_request_url_;
bool is_overriding_user_agent_;
base::Time timestamp_;
+ int http_status_code_;
// This member is not persisted with session restore because it is transient.
// If the post request succeeds, this field is cleared since the same
diff --git a/chromium/content/browser/web_contents/render_view_host_manager.cc b/chromium/content/browser/web_contents/render_view_host_manager.cc
index 9d29a09c6a3..f8b3f06dd27 100644
--- a/chromium/content/browser/web_contents/render_view_host_manager.cc
+++ b/chromium/content/browser/web_contents/render_view_host_manager.cc
@@ -24,6 +24,7 @@
#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_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"
@@ -83,7 +84,7 @@ void RenderViewHostManager::Init(BrowserContext* 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));
+ routing_id, main_frame_routing_id, false, delegate_->IsHidden()));
// Keep track of renderer processes as they start to shut down or are
// crashed/killed.
@@ -200,6 +201,10 @@ bool RenderViewHostManager::ShouldCloseTabOnUnresponsiveRenderer() {
if (!cross_navigation_pending_)
return true;
+ // We should always have a pending RVH when there's a cross-process navigation
+ // in progress. Sanity check this for http://crbug.com/276333.
+ CHECK(pending_render_view_host_);
+
// If the tab becomes unresponsive during {before}unload while doing a
// cross-site navigation, proceed with the navigation. (This assumes that
// the pending RenderViewHost is still responsive.)
@@ -382,6 +387,14 @@ void RenderViewHostManager::SwapOutOldPage() {
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.
+ delegate_->CancelModalDialogsForRenderManager();
+
// Tell the old renderer it is being swapped out. This will fire the unload
// handler (without firing the beforeunload handler a second time). When the
// unload handler finishes and the navigation completes, we will send a
@@ -642,8 +655,10 @@ SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry(
int RenderViewHostManager::CreateRenderView(
SiteInstance* instance,
int opener_route_id,
- bool swapped_out) {
+ bool swapped_out,
+ bool hidden) {
CHECK(instance);
+ DCHECK(!swapped_out || hidden); // Swapped out views should always be hidden.
// 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
@@ -662,7 +677,8 @@ int RenderViewHostManager::CreateRenderView(
render_widget_delegate_,
MSG_ROUTING_NONE,
MSG_ROUTING_NONE,
- swapped_out));
+ swapped_out,
+ hidden));
// If the new RVH is swapped out already, store it. Otherwise prevent the
// process from exiting while we're trying to navigate in it.
@@ -690,9 +706,9 @@ int RenderViewHostManager::CreateRenderView(
bool RenderViewHostManager::InitRenderView(RenderViewHost* render_view_host,
int opener_route_id) {
- // If the pending navigation is to a WebUI, tell the RenderView about any
- // bindings it will need enabled.
- if (pending_web_ui())
+ // 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())
render_view_host->AllowBindings(pending_web_ui()->GetBindings());
return delegate_->CreateRenderViewForRenderManager(render_view_host,
@@ -706,6 +722,14 @@ void RenderViewHostManager::CommitPending() {
// 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.
+ 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.
@@ -740,10 +764,10 @@ void RenderViewHostManager::CommitPending() {
// If the view is gone, then this RenderViewHost died while it was hidden.
// We ignored the RenderProcessGone call at the time, so we should send it now
// to make sure the sad tab shows up, etc.
- if (render_view_host_->GetView())
- render_view_host_->GetView()->Show();
- else
+ if (!render_view_host_->GetView())
delegate_->RenderProcessGoneFromRenderManager(render_view_host_);
+ else if (!delegate_->IsHidden())
+ render_view_host_->GetView()->Show();
// Hide the old view now that the new one is visible.
if (old_render_view_host->GetView()) {
@@ -816,33 +840,16 @@ void RenderViewHostManager::ShutdownRenderViewHostsInSiteInstance(
// list.
swapped_out_hosts_.erase(site_instance_id);
- RenderWidgetHost::List widgets =
- RenderWidgetHostImpl::GetAllRenderWidgetHosts();
-
- // Here deleting a RWH in widgets can possibly cause another RWH in
- // the list to be deleted. This can result in leaving a dangling
- // pointer in the widgets list. Our assumption is that a widget
- // deleted as that sort of side-effect should not be directly
- // deleted here. Therefore, we first gather only widgets directly to
- // be deleted so that we don't hit any future dangling pointers in
- // widgets.
- std::vector<RenderViewHostImpl*> rvhs_to_be_deleted;
-
- for (size_t i = 0; i < widgets.size(); ++i) {
- if (!widgets[i]->IsRenderView())
+ scoped_ptr<RenderWidgetHostIterator> widgets(
+ RenderWidgetHostImpl::GetAllRenderWidgetHosts());
+ while (RenderWidgetHost* widget = widgets->GetNextHost()) {
+ if (!widget->IsRenderView())
continue;
RenderViewHostImpl* rvh =
- static_cast<RenderViewHostImpl*>(RenderViewHost::From(widgets[i]));
- if (site_instance_id == rvh->GetSiteInstance()->GetId()) {
- DCHECK(rvh->is_swapped_out());
- rvhs_to_be_deleted.push_back(rvh);
- }
+ static_cast<RenderViewHostImpl*>(RenderViewHost::From(widget));
+ if (site_instance_id == rvh->GetSiteInstance()->GetId())
+ rvh->Shutdown();
}
-
- // Finally we delete the gathered RVHs, which should not indirectly
- // delete each other.
- for (size_t i = 0; i < rvhs_to_be_deleted.size(); ++i)
- rvhs_to_be_deleted[i]->Shutdown();
}
RenderViewHostImpl* RenderViewHostManager::UpdateRendererStateForNavigate(
@@ -894,7 +901,8 @@ RenderViewHostImpl* RenderViewHostManager::UpdateRendererStateForNavigate(
// Create a non-swapped-out pending RVH with the given opener and navigate
// it.
- int route_id = CreateRenderView(new_instance, opener_route_id, false);
+ int route_id = CreateRenderView(new_instance, opener_route_id, false,
+ delegate_->IsHidden());
if (route_id == MSG_ROUTING_NONE)
return NULL;
diff --git a/chromium/content/browser/web_contents/render_view_host_manager.h b/chromium/content/browser/web_contents/render_view_host_manager.h
index 8c5071d9d65..8f73610b4b5 100644
--- a/chromium/content/browser/web_contents/render_view_host_manager.h
+++ b/chromium/content/browser/web_contents/render_view_host_manager.h
@@ -64,6 +64,7 @@ class CONTENT_EXPORT RenderViewHostManager
virtual void RenderProcessGoneFromRenderManager(
RenderViewHost* render_view_host) = 0;
virtual void UpdateRenderViewSizeForRenderManager() = 0;
+ virtual void CancelModalDialogsForRenderManager() = 0;
virtual void NotifySwappedFromRenderManager(
RenderViewHost* old_render_view_host) = 0;
virtual NavigationControllerImpl&
@@ -97,6 +98,10 @@ class CONTENT_EXPORT RenderViewHostManager
// Creates a view and sets the size for the specified RVH.
virtual void CreateViewAndSetSizeForRVH(RenderViewHost* rvh) = 0;
+ // Returns true if views created for this delegate should be created in a
+ // hidden state.
+ virtual bool IsHidden() = 0;
+
protected:
virtual ~Delegate() {}
};
@@ -181,7 +186,8 @@ class CONTENT_EXPORT RenderViewHostManager
// will be used for a pending cross-site navigation.
int CreateRenderView(SiteInstance* instance,
int opener_route_id,
- bool swapped_out);
+ bool swapped_out,
+ bool hidden);
// Called when a provisional load on the given renderer is aborted.
void RendererAbortedProvisionalLoad(RenderViewHost* render_view_host);
diff --git a/chromium/content/browser/web_contents/render_view_host_manager_unittest.cc b/chromium/content/browser/web_contents/render_view_host_manager_unittest.cc
index ea35e6ba05f..d8837ebc5cc 100644
--- a/chromium/content/browser/web_contents/render_view_host_manager_unittest.cc
+++ b/chromium/content/browser/web_contents/render_view_host_manager_unittest.cc
@@ -16,6 +16,7 @@
#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_ui_controller.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/javascript_message_type.h"
@@ -345,12 +346,14 @@ TEST_F(RenderViewHostManagerTest, GetRenderWidgetHostsReturnsActiveViews) {
TestRenderViewHost* swapped_out_rvh = CreateSwappedOutRenderViewHost();
EXPECT_TRUE(swapped_out_rvh->is_swapped_out());
- RenderWidgetHost::List widgets = RenderWidgetHost::GetRenderWidgetHosts();
+ scoped_ptr<RenderWidgetHostIterator> widgets(
+ RenderWidgetHost::GetRenderWidgetHosts());
// We know that there is the only one active widget. Another view is
// now swapped out, so the swapped out view is not included in the
// list.
- EXPECT_TRUE(widgets.size() == 1);
- RenderViewHost* rvh = RenderViewHost::From(widgets[0]);
+ RenderWidgetHost* widget = widgets->GetNextHost();
+ EXPECT_FALSE(widgets->GetNextHost());
+ RenderViewHost* rvh = RenderViewHost::From(widget);
EXPECT_FALSE(static_cast<RenderViewHostImpl*>(rvh)->is_swapped_out());
}
@@ -364,14 +367,15 @@ TEST_F(RenderViewHostManagerTest,
TestRenderViewHost* swapped_out_rvh = CreateSwappedOutRenderViewHost();
EXPECT_TRUE(swapped_out_rvh->is_swapped_out());
- RenderWidgetHost::List widgets = RenderWidgetHost::GetRenderWidgetHosts();
- RenderWidgetHost::List all_widgets =
- RenderWidgetHostImpl::GetAllRenderWidgetHosts();
+ scoped_ptr<RenderWidgetHostIterator> widgets(
+ RenderWidgetHost::GetRenderWidgetHosts());
- for (size_t i = 0; i < widgets.size(); ++i) {
+ while (RenderWidgetHost* w = widgets->GetNextHost()) {
bool found = false;
- for (size_t j = 0; j < all_widgets.size(); ++j) {
- if (widgets[i] == all_widgets[j]) {
+ scoped_ptr<RenderWidgetHostIterator> all_widgets(
+ RenderWidgetHostImpl::GetAllRenderWidgetHosts());
+ while (RenderWidgetHost* widget = all_widgets->GetNextHost()) {
+ if (w == widget) {
found = true;
break;
}
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 d38f5f5c7f6..ada5976aa7b 100644
--- a/chromium/content/browser/web_contents/touch_editable_impl_aura.cc
+++ b/chromium/content/browser/web_contents/touch_editable_impl_aura.cc
@@ -14,8 +14,8 @@
#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
#include "ui/base/clipboard/clipboard.h"
-#include "ui/base/range/range.h"
#include "ui/base/ui_base_switches_util.h"
+#include "ui/gfx/range/range.h"
namespace content {
@@ -295,7 +295,7 @@ bool TouchEditableImplAura::IsCommandIdEnabled(int command_id) const {
if (!rwhva_)
return false;
bool editable = rwhva_->GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE;
- ui::Range selection_range;
+ gfx::Range selection_range;
rwhva_->GetSelectionRange(&selection_range);
bool has_selection = !selection_range.is_empty();
switch (command_id) {
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 ce0a7027c12..6c5fa2a1bbf 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
@@ -16,18 +16,19 @@
#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/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
#include "ui/aura/root_window.h"
#include "ui/aura/test/event_generator.h"
#include "ui/aura/window.h"
-#include "ui/base/events/event_utils.h"
#include "ui/base/ui_base_switches.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
+#include "ui/events/event_utils.h"
namespace content {
+// TODO(mohsen): Remove logs if the test showed no flakiness anymore.
class TestTouchEditableImplAura : public TouchEditableImplAura {
public:
TestTouchEditableImplAura()
@@ -37,28 +38,61 @@ class TestTouchEditableImplAura : public TouchEditableImplAura {
waiting_for_gesture_ack_callback_(false) {}
void Reset() {
+ LOG(INFO) << "TestTouchEditableImplAura::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()";
if (selection_changed_callback_arrived_)
return;
waiting_for_selection_changed_callback_ = true;
@@ -67,6 +101,7 @@ class TestTouchEditableImplAura : public TouchEditableImplAura {
}
void WaitForGestureAck() {
+ LOG(INFO) << "TestTouchEditableImplAura::WaitForGestureAck()";
if (gesture_ack_callback_arrived_)
return;
waiting_for_gesture_ack_callback_ = true;
@@ -115,6 +150,7 @@ class TouchEditableImplAuraTest : public ContentBrowserTest {
content->GetRootWindow()->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"));
@@ -132,30 +168,40 @@ 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(
gfx::Point(10, 47),
gfx::Point(30, 47),
base::TimeDelta::FromMilliseconds(20),
- 1);
+ 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);
@@ -275,6 +321,7 @@ 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"));
@@ -292,21 +339,32 @@ class TouchEditableImplAuraTest : public ContentBrowserTest {
aura::test::EventGenerator generator(content->GetRootWindow(), content);
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
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;
@@ -314,14 +372,18 @@ 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()");
+ value = content::ExecuteScriptAndGetValue(view_host,
+ "get_cursor_position()");
int new_cursor_pos = -1;
value->GetAsInteger(&new_cursor_pos);
EXPECT_NE(-1, new_cursor_pos);
@@ -348,9 +410,8 @@ IN_PROC_BROWSER_TEST_F(TouchEditableImplAuraTest,
TestTouchSelectionOnLongPress();
}
-// TODO(miu): Disabled test due to flakiness. http://crbug.com/235991
IN_PROC_BROWSER_TEST_F(TouchEditableImplAuraTest,
- DISABLED_TouchCursorInTextfieldTest) {
+ TouchCursorInTextfieldTest) {
TestTouchCursorInTextfield();
}
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 68e27884475..cb24210c3b9 100644
--- a/chromium/content/browser/web_contents/web_contents_drag_win.cc
+++ b/chromium/content/browser/web_contents/web_contents_drag_win.cc
@@ -163,7 +163,7 @@ void WebContentsDragWin::StartDragging(const DropData& drop_data,
drag_source_ = new WebDragSource(source_window_, web_contents_);
- const GURL& page_url = web_contents_->GetURL();
+ const GURL& page_url = web_contents_->GetLastCommittedURL();
const std::string& page_encoding = web_contents_->GetEncoding();
// If it is not drag-out, do the drag-and-drop in the current UI thread.
diff --git a/chromium/content/browser/web_contents/web_contents_impl.cc b/chromium/content/browser/web_contents/web_contents_impl.cc
index 2d19b65e479..26e6baa746d 100644
--- a/chromium/content/browser/web_contents/web_contents_impl.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl.cc
@@ -29,6 +29,7 @@
#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/host_zoom_map_impl.h"
@@ -53,7 +54,6 @@
#include "content/port/browser/render_widget_host_view_port.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/color_chooser.h"
-#include "content/public/browser/compositor_util.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/download_manager.h"
@@ -79,6 +79,9 @@
#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"
@@ -162,15 +165,13 @@ g_created_callbacks = LAZY_INSTANCE_INITIALIZER;
static int StartDownload(content::RenderViewHost* rvh,
const GURL& url,
bool is_favicon,
- uint32_t preferred_image_size,
- uint32_t max_image_size) {
+ uint32_t max_bitmap_size) {
static int g_next_image_download_id = 0;
rvh->Send(new ImageMsg_DownloadImage(rvh->GetRoutingID(),
++g_next_image_download_id,
url,
is_favicon,
- preferred_image_size,
- max_image_size));
+ max_bitmap_size));
return g_next_image_download_id;
}
@@ -265,6 +266,14 @@ void MakeNavigateParams(const NavigationEntryImpl& entry,
delegate->AddNavigationHeaders(params->url, &params->extra_headers);
}
+void NotifyCacheOnIO(
+ scoped_refptr<net::URLRequestContextGetter> request_context,
+ const GURL& url,
+ const std::string& http_method) {
+ request_context->GetURLRequestContext()->http_transaction_factory()->
+ GetCache()->OnExternalCacheHit(url, http_method);
+}
+
} // namespace
WebContents* WebContents::Create(const WebContents::CreateParams& params) {
@@ -554,8 +563,11 @@ WebPreferences WebContentsImpl::GetWebkitPrefs(RenderViewHost* rvh,
}
#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();
@@ -834,6 +846,14 @@ RenderWidgetHostViewPort* WebContentsImpl::GetRenderWidgetHostViewPort() const {
return RenderWidgetHostViewPort::FromRWHV(GetRenderWidgetHostView());
}
+RenderWidgetHostView* WebContentsImpl::GetFullscreenRenderWidgetHostView()
+ const {
+ RenderWidgetHost* const widget_host =
+ RenderWidgetHostImpl::FromID(GetRenderProcessHost()->GetID(),
+ GetFullscreenWidgetRoutingID());
+ return widget_host ? widget_host->GetView() : NULL;
+}
+
WebContentsView* WebContentsImpl::GetView() const {
return view_.get();
}
@@ -1049,9 +1069,7 @@ void WebContentsImpl::DecrementCapturerCount() {
if (is_being_destroyed_)
return;
- // While capturer_count_ was greater than zero, the WasHidden() calls to RWHV
- // were being prevented. If there are no more capturers, make the call now.
- if (capturer_count_ == 0 && !should_normally_be_visible_) {
+ if (IsHidden()) {
DVLOG(1) << "Executing delayed WasHidden().";
WasHidden();
}
@@ -1099,7 +1117,7 @@ void WebContentsImpl::WasShown() {
RenderWidgetHostViewPort* rwhv =
RenderWidgetHostViewPort::FromRWHV(GetRenderWidgetHostView());
if (rwhv) {
- rwhv->WasShown();
+ rwhv->Show();
#if defined(OS_MACOSX)
rwhv->SetActive(true);
#endif
@@ -1137,7 +1155,7 @@ void WebContentsImpl::WasHidden() {
RenderWidgetHostViewPort* rwhv =
RenderWidgetHostViewPort::FromRWHV(GetRenderWidgetHostView());
if (rwhv)
- rwhv->WasHidden();
+ rwhv->Hide();
}
should_normally_be_visible_ = false;
@@ -1157,7 +1175,7 @@ bool WebContentsImpl::NeedToFireBeforeUnload() {
void WebContentsImpl::Stop() {
render_manager_.Stop();
- FOR_EACH_OBSERVER(WebContentsObserver, observers_, StopNavigation());
+ FOR_EACH_OBSERVER(WebContentsObserver, observers_, NavigationStopped());
}
WebContents* WebContentsImpl::Clone() {
@@ -1195,6 +1213,10 @@ void WebContentsImpl::Observe(int type,
}
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.
+ should_normally_be_visible_ = !params.initially_hidden;
+
render_manager_.Init(
params.browser_context, params.site_instance, params.routing_id,
params.main_frame_routing_id);
@@ -1318,6 +1340,8 @@ void WebContentsImpl::RenderWidgetDeleted(
if (render_widget_host &&
render_widget_host->GetRoutingID() == fullscreen_widget_routing_id_) {
+ if (delegate_ && delegate_->EmbedsFullscreenWidget())
+ delegate_->ToggleFullscreenModeForTab(this, false);
FOR_EACH_OBSERVER(WebContentsObserver,
observers_,
DidDestroyFullscreenWidget(
@@ -1395,6 +1419,13 @@ void WebContentsImpl::HandleGestureEnd() {
}
void WebContentsImpl::ToggleFullscreenMode(bool enter_fullscreen) {
+ // This method is being called to enter or leave renderer-initiated fullscreen
+ // mode. Either way, make sure any existing fullscreen widget is shut down
+ // first.
+ RenderWidgetHostView* const widget_view = GetFullscreenRenderWidgetHostView();
+ if (widget_view)
+ RenderWidgetHostImpl::From(widget_view->GetRenderWidgetHost())->Shutdown();
+
if (delegate_)
delegate_->ToggleFullscreenModeForTab(this, enter_fullscreen);
}
@@ -1422,23 +1453,6 @@ void WebContentsImpl::CreateNewWindow(
int main_frame_route_id,
const ViewHostMsg_CreateWindow_Params& params,
SessionStorageNamespace* session_storage_namespace) {
- if (delegate_ &&
- !delegate_->ShouldCreateWebContents(this,
- route_id,
- params.window_container_type,
- params.frame_name,
- params.target_url,
- params.referrer,
- params.disposition,
- params.features,
- params.user_gesture,
- params.opener_suppressed)) {
- GetRenderViewHost()->GetProcess()->ResumeRequestsForView(route_id);
- GetRenderViewHost()->GetProcess()->ResumeRequestsForView(
- main_frame_route_id);
- return;
- }
-
// We usually create the new window in the same BrowsingInstance (group of
// script-related windows), by passing in the current SiteInstance. However,
// if the opener is being suppressed (in a non-guest), we create a new
@@ -1450,12 +1464,6 @@ void WebContentsImpl::CreateNewWindow(
SiteInstance::CreateForURL(GetBrowserContext(), params.target_url) :
GetSiteInstance();
- // Create the new web contents. This will automatically create the new
- // WebContentsView. In the future, we may want to create the view separately.
- WebContentsImpl* new_contents =
- new WebContentsImpl(GetBrowserContext(),
- params.opener_suppressed ? NULL : this);
-
// We must assign the SessionStorageNamespace before calling Init().
//
// http://crbug.com/142685
@@ -1470,6 +1478,27 @@ void WebContentsImpl::CreateNewWindow(
SessionStorageNamespaceImpl* session_storage_namespace_impl =
static_cast<SessionStorageNamespaceImpl*>(session_storage_namespace);
CHECK(session_storage_namespace_impl->IsFromContext(dom_storage_context));
+
+ if (delegate_ &&
+ !delegate_->ShouldCreateWebContents(this,
+ route_id,
+ params.window_container_type,
+ params.frame_name,
+ params.target_url,
+ partition_id,
+ session_storage_namespace)) {
+ GetRenderViewHost()->GetProcess()->ResumeRequestsForView(route_id);
+ GetRenderViewHost()->GetProcess()->ResumeRequestsForView(
+ main_frame_route_id);
+ return;
+ }
+
+ // Create the new web contents. This will automatically create the new
+ // WebContentsView. In the future, we may want to create the view separately.
+ WebContentsImpl* new_contents =
+ new WebContentsImpl(GetBrowserContext(),
+ params.opener_suppressed ? NULL : this);
+
new_contents->GetController().SetSessionStorageNamespace(
partition_id,
session_storage_namespace);
@@ -1488,6 +1517,8 @@ void WebContentsImpl::CreateNewWindow(
BrowserPluginGuest::CreateWithOpener(instance_id, new_contents_impl,
GetBrowserPluginGuest(), !!new_contents_impl->opener());
}
+ if (params.disposition == NEW_BACKGROUND_TAB)
+ create_params.initially_hidden = true;
new_contents->Init(create_params);
// Save the window for later if we're not suppressing the opener (since it
@@ -1549,7 +1580,7 @@ void WebContentsImpl::CreateNewWidget(int route_id,
WebKit::WebPopupType popup_type) {
RenderProcessHost* process = GetRenderProcessHost();
RenderWidgetHostImpl* widget_host =
- new RenderWidgetHostImpl(this, process, route_id);
+ new RenderWidgetHostImpl(this, process, route_id, IsHidden());
created_widgets_.insert(widget_host);
RenderWidgetHostViewPort* widget_view = RenderWidgetHostViewPort::FromRWHV(
@@ -1591,12 +1622,6 @@ void WebContentsImpl::ShowCreatedWidget(int route_id,
void WebContentsImpl::ShowCreatedFullscreenWidget(int route_id) {
ShowCreatedWidget(route_id, true, gfx::Rect());
-
- DCHECK_EQ(MSG_ROUTING_NONE, fullscreen_widget_routing_id_);
- fullscreen_widget_routing_id_ = route_id;
- FOR_EACH_OBSERVER(WebContentsObserver,
- observers_,
- DidShowFullscreenWidget(route_id));
}
void WebContentsImpl::ShowCreatedWidget(int route_id,
@@ -1609,17 +1634,35 @@ void WebContentsImpl::ShowCreatedWidget(int route_id,
RenderWidgetHostViewPort::FromRWHV(GetCreatedWidget(route_id));
if (!widget_host_view)
return;
- if (is_fullscreen)
- widget_host_view->InitAsFullscreen(GetRenderWidgetHostViewPort());
- else
+ bool allow_privileged = false;
+ if (is_fullscreen) {
+ 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));
+ if (!widget_host_view->HasFocus())
+ widget_host_view->Focus();
+ } else {
widget_host_view->InitAsPopup(GetRenderWidgetHostViewPort(), initial_pos);
+ }
RenderWidgetHostImpl* render_widget_host_impl =
RenderWidgetHostImpl::From(widget_host_view->GetRenderWidgetHost());
render_widget_host_impl->Init();
- // 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);
+ 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.
#if defined(OS_MACOSX)
// A RenderWidgetHostViewMac has lifetime scoped to the view. Now that it's
@@ -1746,6 +1789,12 @@ void WebContentsImpl::AttachInterstitialPage(
InterstitialPageImpl* interstitial_page) {
DCHECK(interstitial_page);
render_manager_.set_interstitial_page(interstitial_page);
+
+ // Cancel any visible dialogs so that they don't interfere with the
+ // interstitial.
+ if (dialog_manager_)
+ dialog_manager_->CancelActiveAndPendingDialogs(this);
+
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
DidAttachInterstitialPage());
}
@@ -1764,8 +1813,11 @@ 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)
+ if (entry.GetURL().spec().size() > kMaxURLChars) {
+ LOG(WARNING) << "Refusing to load URL as it exceeds " << kMaxURLChars
+ << " characters.";
return false;
+ }
RenderViewHostImpl* dest_render_view_host =
static_cast<RenderViewHostImpl*>(render_manager_.Navigate(entry));
@@ -1806,7 +1858,7 @@ bool WebContentsImpl::NavigateToEntry(
// do not generate content. What we really need is a message from the
// renderer telling us that a new page was not created. The same message
// could be used for mailto: URLs and the like.
- if (entry.GetURL().SchemeIs(chrome::kJavaScriptScheme))
+ if (entry.GetURL().SchemeIs(kJavaScriptScheme))
return false;
}
@@ -1931,8 +1983,8 @@ void WebContentsImpl::SaveFrame(const GURL& url,
void WebContentsImpl::GenerateMHTML(
const base::FilePath& file,
- const base::Callback<void(const base::FilePath&, int64)>& callback) {
- MHTMLGenerationManager::GetInstance()->GenerateMHTML(this, file, callback);
+ const base::Callback<void(int64)>& callback) {
+ MHTMLGenerationManager::GetInstance()->SaveMHTML(this, file, callback);
}
bool WebContentsImpl::IsActiveEntry(int32 page_id) {
@@ -2098,12 +2150,10 @@ void WebContentsImpl::DidEndColorChooser() {
int WebContentsImpl::DownloadImage(const GURL& url,
bool is_favicon,
- uint32_t preferred_image_size,
- uint32_t max_image_size,
+ uint32_t max_bitmap_size,
const ImageDownloadCallback& callback) {
RenderViewHost* host = GetRenderViewHost();
- int id = StartDownload(
- host, url, is_favicon, preferred_image_size, max_image_size);
+ int id = StartDownload(host, url, is_favicon, max_bitmap_size);
image_download_map_[id] = callback;
return id;
}
@@ -2155,6 +2205,13 @@ void WebContentsImpl::DidStartProvisionalLoadForFrame(
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);
}
@@ -2180,8 +2237,8 @@ void WebContentsImpl::DidRedirectProvisionalLoad(
const GURL& source_url,
const GURL& target_url) {
// TODO(creis): Remove this method and have the pre-rendering code listen to
- // the ResourceDispatcherHost's RESOURCE_RECEIVED_REDIRECT notification
- // instead. See http://crbug.com/78512.
+ // WebContentsObserver::DidGetRedirectForResourceRequest instead.
+ // See http://crbug.com/78512.
GURL validated_source_url(source_url);
GURL validated_target_url(target_url);
RenderProcessHost* render_process_host =
@@ -2288,10 +2345,29 @@ void WebContentsImpl::OnDidLoadResourceFromMemoryCache(
url, GetRenderProcessHost()->GetID(), cert_id, cert_status, http_method,
mime_type, resource_type);
+ controller_.ssl_manager()->DidLoadFromMemoryCache(details);
+
+ 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 ?
+ GetBrowserContext()->GetMediaRequestContextForRenderProcess(
+ GetRenderProcessHost()->GetID()) :
+ GetBrowserContext()->GetRequestContextForRenderProcess(
+ GetRenderProcessHost()->GetID()));
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&NotifyCacheOnIO, request_context, url, http_method));
+ }
}
void WebContentsImpl::OnDidDisplayInsecureContent() {
@@ -2438,10 +2514,20 @@ void WebContentsImpl::OnFindMatchRectsReply(
void WebContentsImpl::OnOpenDateTimeDialog(
const ViewHostMsg_DateTimeDialogValue_Params& value) {
- date_time_chooser_->ShowDialog(
- ContentViewCore::FromWebContents(this), GetRenderViewHost(),
- value.dialog_type, value.year, value.month, value.day, value.hour,
- value.minute, value.second, value.week, value.minimum, value.maximum);
+ 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.minimum,
+ value.maximum,
+ value.step);
}
#endif
@@ -2537,8 +2623,8 @@ void WebContentsImpl::OnDidDownloadImage(
int id,
int http_status_code,
const GURL& image_url,
- int requested_size,
- const std::vector<SkBitmap>& bitmaps) {
+ const std::vector<SkBitmap>& bitmaps,
+ const std::vector<gfx::Size>& original_bitmap_sizes) {
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
@@ -2546,7 +2632,8 @@ void WebContentsImpl::OnDidDownloadImage(
return;
}
if (!iter->second.is_null()) {
- iter->second.Run(id, http_status_code, image_url, requested_size, bitmaps);
+ iter->second.Run(
+ id, http_status_code, image_url, bitmaps, original_bitmap_sizes);
}
image_download_map_.erase(id);
}
@@ -2794,6 +2881,10 @@ void WebContentsImpl::NotifySwapped(RenderViewHost* old_render_view_host) {
// notification so that clients that pick up a pointer to |this| can NULL the
// pointer. See Bug 1230284.
notify_disconnection_ = true;
+ FOR_EACH_OBSERVER(WebContentsObserver, observers_,
+ RenderViewHostSwapped(old_render_view_host));
+
+ // TODO(avi): Remove. http://crbug.com/170921
NotificationService::current()->Notify(
NOTIFICATION_WEB_CONTENTS_SWAPPED,
Source<WebContents>(this),
@@ -2805,14 +2896,8 @@ void WebContentsImpl::NotifySwapped(RenderViewHost* old_render_view_host) {
RemoveBrowserPluginEmbedder();
}
-void WebContentsImpl::NotifyConnected() {
- notify_disconnection_ = true;
- NotificationService::current()->Notify(
- NOTIFICATION_WEB_CONTENTS_CONNECTED,
- Source<WebContents>(this),
- NotificationService::NoDetails());
-}
-
+// TODO(avi): Remove this entire function because this notification is already
+// covered by two observer functions. http://crbug.com/170921
void WebContentsImpl::NotifyDisconnected() {
if (!notify_disconnection_)
return;
@@ -2899,7 +2984,13 @@ void WebContentsImpl::RenderViewReady(RenderViewHost* rvh) {
return;
}
- NotifyConnected();
+ notify_disconnection_ = true;
+ // TODO(avi): Remove. http://crbug.com/170921
+ NotificationService::current()->Notify(
+ NOTIFICATION_WEB_CONTENTS_CONNECTED,
+ Source<WebContents>(this),
+ NotificationService::NoDetails());
+
bool was_crashed = IsCrashed();
SetIsCrashed(base::TERMINATION_STATUS_STILL_RUNNING, 0);
@@ -2938,6 +3029,34 @@ void WebContentsImpl::RenderViewDeleted(RenderViewHost* rvh) {
FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewDeleted(rvh));
}
+void WebContentsImpl::DidGetResourceResponseStart(
+ const ResourceRequestDetails& details) {
+ controller_.ssl_manager()->DidStartResourceResponse(details);
+
+ FOR_EACH_OBSERVER(WebContentsObserver, observers_,
+ DidGetResourceResponseStart(details));
+
+ // TODO(avi): Remove. http://crbug.com/170921
+ NotificationService::current()->Notify(
+ NOTIFICATION_RESOURCE_RESPONSE_STARTED,
+ Source<WebContents>(this),
+ Details<const ResourceRequestDetails>(&details));
+}
+
+void WebContentsImpl::DidGetRedirectForResourceRequest(
+ const ResourceRedirectDetails& details) {
+ controller_.ssl_manager()->DidReceiveResourceRedirect(details);
+
+ FOR_EACH_OBSERVER(WebContentsObserver, observers_,
+ DidGetRedirectForResourceRequest(details));
+
+ // TODO(avi): Remove. http://crbug.com/170921
+ NotificationService::current()->Notify(
+ NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
+ Source<WebContents>(this),
+ Details<const ResourceRedirectDetails>(&details));
+}
+
void WebContentsImpl::DidNavigate(
RenderViewHost* rvh,
const ViewHostMsg_FrameNavigate_Params& params) {
@@ -3179,10 +3298,8 @@ void WebContentsImpl::DidCancelLoading() {
}
void WebContentsImpl::DidChangeLoadProgress(double progress) {
-#if defined(OS_ANDROID)
if (delegate_)
delegate_->LoadProgressChanged(this, progress);
-#endif
}
void WebContentsImpl::DidDisownOpener(RenderViewHost* rvh) {
@@ -3250,6 +3367,11 @@ void WebContentsImpl::RequestTransferURL(
bool user_gesture) {
WebContents* new_contents = NULL;
PageTransition transition_type = PAGE_TRANSITION_LINK;
+ GURL dest_url(url);
+ if (!GetContentClient()->browser()->ShouldAllowOpenURL(
+ 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
@@ -3259,14 +3381,14 @@ void WebContentsImpl::RequestTransferURL(
// 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(url, Referrer(), source_frame_id, disposition,
+ 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(url, referrer, source_frame_id, disposition,
+ 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;
@@ -3277,7 +3399,7 @@ void WebContentsImpl::RequestTransferURL(
// Notify observers.
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
DidOpenRequestedURL(new_contents,
- url,
+ dest_url,
referrer,
disposition,
transition_type,
@@ -3384,13 +3506,16 @@ void WebContentsImpl::RunJavaScriptMessage(
&suppress_this_message);
}
+ *did_suppress_message = suppress_this_message;
+
if (suppress_this_message) {
// If we are suppressing messages, just reply as if the user immediately
// pressed "Cancel".
OnDialogClosed(rvh, reply_msg, false, string16());
}
- *did_suppress_message = suppress_this_message;
+ // OnDialogClosed (two lines up) may have caused deletion of this object (see
+ // http://crbug.com/288961 ). The only safe thing to do here is return.
}
void WebContentsImpl::RunBeforeUnloadConfirm(RenderViewHost* rvh,
@@ -3440,7 +3565,8 @@ WebPreferences WebContentsImpl::GetWebkitPrefs() {
int WebContentsImpl::CreateSwappedOutRenderView(
SiteInstance* instance) {
- return render_manager_.CreateRenderView(instance, MSG_ROUTING_NONE, true);
+ return render_manager_.CreateRenderView(instance, MSG_ROUTING_NONE,
+ true, true);
}
void WebContentsImpl::OnUserGesture() {
@@ -3458,6 +3584,7 @@ void WebContentsImpl::OnIgnoredUIEvent() {
}
void WebContentsImpl::RendererUnresponsive(RenderViewHost* rvh,
+ bool is_during_beforeunload,
bool is_during_unload) {
// Don't show hung renderer dialog for a swapped out RVH.
if (rvh != GetRenderViewHost())
@@ -3471,7 +3598,7 @@ void WebContentsImpl::RendererUnresponsive(RenderViewHost* rvh,
if (DevToolsAgentHost::IsDebuggerAttached(this))
return;
- if (is_during_unload) {
+ if (is_during_beforeunload || is_during_unload) {
// Hang occurred while firing the beforeunload/unload handler.
// Pretend the handler fired so tab closing continues as if it had.
rvhi->set_sudden_termination_allowed(true);
@@ -3480,10 +3607,17 @@ void WebContentsImpl::RendererUnresponsive(RenderViewHost* rvh,
return;
// If the tab hangs in the beforeunload/unload handler there's really
- // nothing we can do to recover. Pretend the unload listeners have
- // all fired and close the tab. If the hang is in the beforeunload handler
- // then the user will not have the option of cancelling the close.
- Close(rvh);
+ // nothing we can do to recover. If the hang is in the beforeunload handler,
+ // pretend the beforeunload listeners have all fired and allow the delegate
+ // to continue closing; the user will not have the option of cancelling the
+ // close. Otherwise, pretend the unload listeners have all fired and close
+ // the tab.
+ bool close = true;
+ if (is_during_beforeunload) {
+ delegate_->BeforeUnloadFired(this, true, &close);
+ }
+ if (close)
+ Close(rvh);
return;
}
@@ -3540,7 +3674,7 @@ void WebContentsImpl::RenderProcessGoneFromRenderManager(
void WebContentsImpl::UpdateRenderViewSizeForRenderManager() {
// TODO(brettw) this is a hack. See WebContentsView::SizeContents.
- gfx::Size size = view_->GetContainerSize();
+ gfx::Size size = GetSizeForNewRenderView();
// 0x0 isn't a valid window size (minimal window size is 1x1) but it may be
// here during container initialization and normal window size will be set
// later. In case of tab duplication this resizing to 0x0 prevents setting
@@ -3549,6 +3683,13 @@ void WebContentsImpl::UpdateRenderViewSizeForRenderManager() {
view_->SizeContents(size);
}
+void WebContentsImpl::CancelModalDialogsForRenderManager() {
+ // We need to cancel modal dialogs when doing a process swap, since the load
+ // deferrer would prevent us from swapping out.
+ if (dialog_manager_)
+ dialog_manager_->CancelActiveAndPendingDialogs(this);
+}
+
void WebContentsImpl::NotifySwappedFromRenderManager(RenderViewHost* rvh) {
NotifySwapped(rvh);
@@ -3610,7 +3751,8 @@ int WebContentsImpl::CreateOpenerRenderViews(SiteInstance* instance) {
// 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);
+ return render_manager_.CreateRenderView(instance, opener_route_id,
+ true, true);
}
NavigationControllerImpl& WebContentsImpl::GetControllerForRenderManager() {
@@ -3634,7 +3776,7 @@ bool WebContentsImpl::CreateRenderViewForRenderManager(
// Now that the RenderView has been created, we need to tell it its size.
if (rwh_view)
- rwh_view->SetSize(view_->GetContainerSize());
+ rwh_view->SetSize(GetSizeForNewRenderView());
// Make sure we use the correct starting page_id in the new RenderView.
UpdateMaxPageIDIfNecessary(render_view_host);
@@ -3648,7 +3790,7 @@ bool WebContentsImpl::CreateRenderViewForRenderManager(
return false;
}
-#if defined(OS_LINUX) || defined(OS_OPENBSD)
+#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
// Force a ViewMsg_Resize to be sent, needed to make plugins show up on
// linux. See crbug.com/83941.
if (rwh_view) {
@@ -3697,6 +3839,10 @@ void WebContentsImpl::CreateViewAndSetSizeForRVH(RenderViewHost* rvh) {
rwh_view->SetSize(GetView()->GetContainerSize());
}
+bool WebContentsImpl::IsHidden() {
+ return capturer_count_ == 0 && !should_normally_be_visible_;
+}
+
RenderViewHostImpl* WebContentsImpl::GetRenderViewHostImpl() {
return static_cast<RenderViewHostImpl*>(GetRenderViewHost());
}
@@ -3734,4 +3880,13 @@ void WebContentsImpl::ClearAllPowerSaveBlockers() {
power_save_blockers_.clear();
}
+gfx::Size WebContentsImpl::GetSizeForNewRenderView() const {
+ gfx::Size size;
+ if (delegate_)
+ size = delegate_->GetSizeForNewRenderView(this);
+ if (size.IsEmpty())
+ size = view_->GetContainerSize();
+ return size;
+}
+
} // 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 a5eaf7ddcbe..c60aebacb30 100644
--- a/chromium/content/browser/web_contents/web_contents_impl.h
+++ b/chromium/content/browser/web_contents/web_contents_impl.h
@@ -223,6 +223,8 @@ class CONTENT_EXPORT WebContentsImpl
virtual int GetEmbeddedInstanceID() const OVERRIDE;
virtual int GetRoutingID() const OVERRIDE;
virtual RenderWidgetHostView* GetRenderWidgetHostView() const OVERRIDE;
+ virtual RenderWidgetHostView* GetFullscreenRenderWidgetHostView() const
+ OVERRIDE;
virtual WebContentsView* GetView() const OVERRIDE;
virtual WebUI* CreateWebUI(const GURL& url) OVERRIDE;
virtual WebUI* GetWebUI() const OVERRIDE;
@@ -275,7 +277,7 @@ class CONTENT_EXPORT WebContentsImpl
const Referrer& referrer) OVERRIDE;
virtual void GenerateMHTML(
const base::FilePath& file,
- const base::Callback<void(const base::FilePath&, int64)>& callback)
+ const base::Callback<void(int64)>& callback)
OVERRIDE;
virtual bool IsActiveEntry(int32 page_id) OVERRIDE;
@@ -304,8 +306,7 @@ class CONTENT_EXPORT WebContentsImpl
virtual void DidEndColorChooser() OVERRIDE;
virtual int DownloadImage(const GURL& url,
bool is_favicon,
- uint32_t preferred_image_size,
- uint32_t max_image_size,
+ uint32_t max_bitmap_size,
const ImageDownloadCallback& callback) OVERRIDE;
// Implementation of PageNavigator.
@@ -347,6 +348,10 @@ class CONTENT_EXPORT WebContentsImpl
RenderViewHost* render_view_host,
const ViewHostMsg_DidFailProvisionalLoadWithError_Params& params)
OVERRIDE;
+ virtual void DidGetResourceResponseStart(
+ const ResourceRequestDetails& details) OVERRIDE;
+ virtual void DidGetRedirectForResourceRequest(
+ const ResourceRedirectDetails& details) OVERRIDE;
virtual void DidNavigate(
RenderViewHost* render_view_host,
const ViewHostMsg_FrameNavigate_Params& params) OVERRIDE;
@@ -414,6 +419,7 @@ class CONTENT_EXPORT WebContentsImpl
virtual void OnUserGesture() OVERRIDE;
virtual void OnIgnoredUIEvent() OVERRIDE;
virtual void RendererUnresponsive(RenderViewHost* render_view_host,
+ bool is_during_beforeunload,
bool is_during_unload) OVERRIDE;
virtual void RendererResponsive(RenderViewHost* render_view_host) OVERRIDE;
virtual void LoadStateChanged(const GURL& url,
@@ -487,6 +493,7 @@ class CONTENT_EXPORT WebContentsImpl
virtual void RenderProcessGoneFromRenderManager(
RenderViewHost* render_view_host) OVERRIDE;
virtual void UpdateRenderViewSizeForRenderManager() OVERRIDE;
+ virtual void CancelModalDialogsForRenderManager() OVERRIDE;
virtual void NotifySwappedFromRenderManager(
RenderViewHost* old_render_view_host) OVERRIDE;
virtual int CreateOpenerRenderViewsForRenderManager(
@@ -499,6 +506,7 @@ class CONTENT_EXPORT WebContentsImpl
virtual bool FocusLocationBarByDefault() OVERRIDE;
virtual void SetFocusToLocationBar(bool select_all) OVERRIDE;
virtual void CreateViewAndSetSizeForRVH(RenderViewHost* rvh) OVERRIDE;
+ virtual bool IsHidden() OVERRIDE;
// NotificationObserver ------------------------------------------------------
@@ -625,8 +633,8 @@ class CONTENT_EXPORT WebContentsImpl
void OnDidDownloadImage(int id,
int http_status_code,
const GURL& image_url,
- int requested_size,
- const std::vector<SkBitmap>& bitmaps);
+ const std::vector<SkBitmap>& bitmaps,
+ const std::vector<gfx::Size>& original_bitmap_sizes);
void OnUpdateFaviconURL(int32 page_id,
const std::vector<FaviconURL>& candidates);
void OnFrameAttached(int64 parent_frame_id,
@@ -738,7 +746,6 @@ class CONTENT_EXPORT WebContentsImpl
// Helper functions for sending notifications.
void NotifySwapped(RenderViewHost* old_render_view_host);
- void NotifyConnected();
void NotifyDisconnected();
void NotifyNavigationEntryCommitted(const LoadCommittedDetails& load_details);
@@ -757,6 +764,9 @@ class CONTENT_EXPORT WebContentsImpl
// Clear all PowerSaveBlockers, leave power_save_blocker_ empty.
void ClearAllPowerSaveBlockers();
+ // Helper function to invoke WebContentsDelegate::GetSizeForNewRenderView().
+ gfx::Size GetSizeForNewRenderView() const;
+
// Data for core operation ---------------------------------------------------
// Delegate for notifying our owner about stuff. Not owned by us.
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 5ea20a6affa..651c2b7d637 100644
--- a/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -10,17 +10,38 @@
#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_widget_host_view.h"
#include "content/public/browser/web_contents_observer.h"
+#include "content/public/browser/web_contents_view.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/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
namespace content {
+void ResizeWebContentsView(Shell* shell, const gfx::Size& size,
+ bool set_start_page) {
+ // Shell::SizeTo is not implemented on Aura; WebContentsView::SizeContents
+ // works on Win and ChromeOS but not Linux - we need to resize the shell
+ // window on Linux because if we don't, the next layout of the unchanged shell
+ // window will resize WebContentsView back to the previous 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());
+ // If |set_start_page| is true, start with blank page to make sure resize
+ // takes effect.
+ if (set_start_page)
+ NavigateToURL(shell, GURL("about://blank"));
+#else
+ shell->web_contents()->GetView()->SizeContents(size);
+#endif // defined(TOOLKIT_GTK) || defined(OS_MACOSX)
+}
+
class WebContentsImplBrowserTest : public ContentBrowserTest {
public:
WebContentsImplBrowserTest() {}
@@ -82,6 +103,51 @@ class NavigateOnCommitObserver : public WebContentsObserver {
bool done_;
};
+class RenderViewSizeDelegate : public WebContentsDelegate {
+ public:
+ void set_size_insets(const gfx::Size& size_insets) {
+ size_insets_ = size_insets;
+ }
+
+ // WebContentsDelegate:
+ virtual gfx::Size GetSizeForNewRenderView(
+ const WebContents* web_contents) const OVERRIDE {
+ gfx::Size size(web_contents->GetView()->GetContainerSize());
+ size.Enlarge(size_insets_.width(), size_insets_.height());
+ return size;
+ }
+
+ private:
+ gfx::Size size_insets_;
+};
+
+class RenderViewSizeObserver : public WebContentsObserver {
+ public:
+ RenderViewSizeObserver(Shell* shell, const gfx::Size& wcv_new_size)
+ : WebContentsObserver(shell->web_contents()),
+ shell_(shell),
+ wcv_new_size_(wcv_new_size) {
+ }
+
+ // WebContentsObserver:
+ virtual void RenderViewCreated(RenderViewHost* rvh) OVERRIDE {
+ rwhv_create_size_ = rvh->GetView()->GetViewBounds().size();
+ }
+
+ virtual void NavigateToPendingEntry(
+ const GURL& url,
+ NavigationController::ReloadType reload_type) OVERRIDE {
+ ResizeWebContentsView(shell_, wcv_new_size_, false);
+ }
+
+ gfx::Size rwhv_create_size() const { return rwhv_create_size_; }
+
+ private:
+ Shell* shell_; // Weak ptr.
+ gfx::Size wcv_new_size_;
+ gfx::Size rwhv_create_size_;
+};
+
// Test that DidStopLoading includes the correct URL in the details.
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, DidStopLoadingDetails) {
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
@@ -186,4 +252,71 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, FrameTree) {
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
+// force-compositing-mode is resolved (http://crbug.com/281726).
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_ANDROID)
+#define MAYBE_GetSizeForNewRenderView DISABLED_GetSizeForNewRenderView
+#else
+#define MAYBE_GetSizeForNewRenderView GetSizeForNewRenderView
+#endif
+// Test that RenderViewHost is created and updated at the size specified by
+// WebContentsDelegate::GetSizeForNewRenderView().
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+ MAYBE_GetSizeForNewRenderView) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ // Create a new server with a different site.
+ net::SpawnedTestServer https_server(
+ net::SpawnedTestServer::TYPE_HTTPS,
+ net::SpawnedTestServer::kLocalhost,
+ base::FilePath(FILE_PATH_LITERAL("content/test/data")));
+ ASSERT_TRUE(https_server.Start());
+
+ scoped_ptr<RenderViewSizeDelegate> delegate(new RenderViewSizeDelegate());
+ shell()->web_contents()->SetDelegate(delegate.get());
+ ASSERT_TRUE(shell()->web_contents()->GetDelegate() == delegate.get());
+
+ // When no size is set, RenderWidgetHostView adopts the size of
+ // WebContenntsView.
+ NavigateToURL(shell(), embedded_test_server()->GetURL("/title2.html"));
+ EXPECT_EQ(shell()->web_contents()->GetView()->GetContainerSize(),
+ shell()->web_contents()->GetRenderWidgetHostView()->GetViewBounds().
+ size());
+
+ // When a size is set, RenderWidgetHostView and WebContentsView honor this
+ // size.
+ gfx::Size size(300, 300);
+ gfx::Size size_insets(-10, -15);
+ ResizeWebContentsView(shell(), size, true);
+ delegate->set_size_insets(size_insets);
+ NavigateToURL(shell(), https_server.GetURL("/"));
+ size.Enlarge(size_insets.width(), size_insets.height());
+ EXPECT_EQ(size,
+ shell()->web_contents()->GetRenderWidgetHostView()->GetViewBounds().
+ size());
+ EXPECT_EQ(size, shell()->web_contents()->GetView()->GetContainerSize());
+
+ // If WebContentsView is resized after RenderWidgetHostView is created but
+ // before pending navigation entry is committed, both RenderWidgetHostView and
+ // WebContentsView use the new size of WebContentsView.
+ gfx::Size init_size(200, 200);
+ gfx::Size new_size(100, 100);
+ size_insets = gfx::Size(-20, -30);
+ ResizeWebContentsView(shell(), init_size, true);
+ delegate->set_size_insets(size_insets);
+ RenderViewSizeObserver observer(shell(), new_size);
+ NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
+ // 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.
+ new_size.Enlarge(size_insets.width(), size_insets.height());
+ EXPECT_EQ(new_size,
+ shell()->web_contents()->GetRenderWidgetHostView()->GetViewBounds().
+ size());
+ EXPECT_EQ(new_size, shell()->web_contents()->GetView()->GetContainerSize());
+}
+
} // namespace content
diff --git a/chromium/content/browser/web_contents/web_contents_screenshot_manager.cc b/chromium/content/browser/web_contents/web_contents_screenshot_manager.cc
index b2eeb464265..811e4ea7fbc 100644
--- a/chromium/content/browser/web_contents/web_contents_screenshot_manager.cc
+++ b/chromium/content/browser/web_contents/web_contents_screenshot_manager.cc
@@ -149,7 +149,8 @@ void WebContentsScreenshotManager::OnScreenshotTaken(int unique_id,
}
if (!success || bitmap.empty() || bitmap.isNull()) {
- ClearScreenshot(entry);
+ if (!ClearScreenshot(entry))
+ OnScreenshotSet(entry);
return;
}
@@ -193,7 +194,8 @@ void WebContentsScreenshotManager::OnScreenshotEncodeComplete(
}
void WebContentsScreenshotManager::OnScreenshotSet(NavigationEntryImpl* entry) {
- PurgeScreenshotsIfNecessary();
+ if (entry->screenshot().get())
+ PurgeScreenshotsIfNecessary();
}
bool WebContentsScreenshotManager::ClearScreenshot(NavigationEntryImpl* entry) {
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 1f7b247e606..b51449e2e40 100644
--- a/chromium/content/browser/web_contents/web_contents_view_android.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_android.cc
@@ -6,13 +6,13 @@
#include "base/logging.h"
#include "content/browser/android/content_view_core_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"
-#include "media/base/android/media_player_manager.h"
namespace content {
WebContentsViewPort* CreateWebContentsView(
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 013edc7fe3e..f3822f8b1c6 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_aura.cc
@@ -35,6 +35,7 @@
#include "content/public/browser/web_drag_dest_delegate.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/drop_data.h"
+#include "net/base/net_util.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/drag_drop_client.h"
@@ -48,11 +49,11 @@
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/drag_utils.h"
#include "ui/base/dragdrop/os_exchange_data.h"
-#include "ui/base/events/event.h"
-#include "ui/base/events/event_utils.h"
#include "ui/base/hit_test.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/events/event.h"
+#include "ui/events/event_utils.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_png_rep.h"
@@ -235,9 +236,34 @@ class WebDragSourceAura : public base::MessageLoopForUI::Observer,
DISALLOW_COPY_AND_ASSIGN(WebDragSourceAura);
};
+#if defined(OS_WIN)
+// Fill out the OSExchangeData with a file contents, synthesizing a name if
+// necessary.
+void PrepareDragForFileContents(const DropData& drop_data,
+ ui::OSExchangeData::Provider* provider) {
+ base::FilePath file_name(drop_data.file_description_filename);
+ // 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();
+ // 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);
+}
+#endif
+
// Utility to fill a ui::OSExchangeDataProvider object from DropData.
void PrepareDragData(const DropData& drop_data,
ui::OSExchangeData::Provider* provider) {
+#if defined(OS_WIN)
+ // We set the file contents before the URL because the URL also sets file
+ // contents (to a .URL shortcut). We want to prefer file content data over
+ // a shortcut so we add it first.
+ if (!drop_data.file_contents.empty())
+ PrepareDragForFileContents(drop_data, provider);
+#endif
if (!drop_data.text.string().empty())
provider->SetString(drop_data.text.string());
if (drop_data.url.is_valid())
@@ -909,7 +935,7 @@ void WebContentsViewAura::ResetOverscrollTransform() {
ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
settings.SetPreemptionStrategy(
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
- settings.SetTweenType(ui::Tween::EASE_OUT);
+ settings.SetTweenType(gfx::Tween::EASE_OUT);
settings.AddObserver(this);
target->SetTransform(gfx::Transform());
}
@@ -917,7 +943,7 @@ void WebContentsViewAura::ResetOverscrollTransform() {
ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
settings.SetPreemptionStrategy(
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
- settings.SetTweenType(ui::Tween::EASE_OUT);
+ settings.SetTweenType(gfx::Tween::EASE_OUT);
UpdateOverscrollWindowBrightness(0.f);
}
}
@@ -942,7 +968,7 @@ void WebContentsViewAura::CompleteOverscrollNavigation(OverscrollMode mode) {
ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
settings.SetPreemptionStrategy(
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
- settings.SetTweenType(ui::Tween::EASE_OUT);
+ settings.SetTweenType(gfx::Tween::EASE_OUT);
settings.AddObserver(this);
gfx::Transform transform;
int content_width =
@@ -1169,13 +1195,15 @@ RenderWidgetHostView* WebContentsViewAura::CreateViewForWidget(
navigation_overlay_->StartObservingView(ToRenderWidgetHostViewAura(view));
}
- view->Show();
+ RenderWidgetHostImpl* host_impl =
+ RenderWidgetHostImpl::From(render_widget_host);
+
+ if (!host_impl->is_hidden())
+ view->Show();
// We listen to drag drop events in the newly created view's window.
aura::client::SetDragDropDelegate(view->GetNativeView(), this);
- RenderWidgetHostImpl* host_impl =
- RenderWidgetHostImpl::From(render_widget_host);
if (host_impl->overscroll_controller() &&
(!web_contents_->GetDelegate() ||
web_contents_->GetDelegate()->CanOverscrollContent())) {
@@ -1227,11 +1255,12 @@ void WebContentsViewAura::SetOverscrollControllerEnabled(bool enabled) {
// WebContentsViewAura, RenderViewHostDelegateView implementation:
void WebContentsViewAura::ShowContextMenu(const ContextMenuParams& params) {
- if (delegate_)
- delegate_->ShowContextMenu(params);
if (touch_editable_)
touch_editable_->EndTouchEditing();
-
+ if (delegate_) {
+ delegate_->ShowContextMenu(params);
+ // WARNING: we may have been deleted during the call to ShowContextMenu().
+ }
}
void WebContentsViewAura::ShowPopupMenu(const gfx::Rect& bounds,
@@ -1507,11 +1536,8 @@ bool WebContentsViewAura::HasHitTestMask() const {
void WebContentsViewAura::GetHitTestMask(gfx::Path* mask) const {
}
-scoped_refptr<ui::Texture> WebContentsViewAura::CopyTexture() {
- // The layer we create doesn't have an external texture, so this should never
- // get invoked.
- NOTREACHED();
- return scoped_refptr<ui::Texture>();
+void WebContentsViewAura::DidRecreateLayer(ui::Layer *old_layer,
+ ui::Layer *new_layer) {
}
////////////////////////////////////////////////////////////////////////////////
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 ca1f99c0a06..aca720e0763 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura.h
+++ b/chromium/content/browser/web_contents/web_contents_view_aura.h
@@ -172,7 +172,8 @@ class CONTENT_EXPORT WebContentsViewAura
virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE;
virtual bool HasHitTestMask() const OVERRIDE;
virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE;
- virtual scoped_refptr<ui::Texture> CopyTexture() OVERRIDE;
+ virtual void DidRecreateLayer(ui::Layer* old_layer,
+ ui::Layer* new_layer) OVERRIDE;
// Overridden from ui::EventHandler:
virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
diff --git a/chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc b/chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc
index e0f34abe4fc..a48cde5b170 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
@@ -9,16 +9,20 @@
#include "base/strings/utf_string_conversions.h"
#include "base/test/test_timeouts.h"
#include "base/values.h"
+#if defined(OS_WIN)
+#include "base/win/windows_version.h"
+#endif
#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"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_utils.h"
-#include "content/shell/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
#include "ui/aura/root_window.h"
@@ -44,6 +48,7 @@ class ScreenshotTracker : public WebContentsScreenshotManager {
void Reset() {
screenshot_taken_for_ = NULL;
+ screenshot_set_.clear();
}
void SetScreenshotInterval(int interval_ms) {
@@ -57,6 +62,10 @@ class ScreenshotTracker : public WebContentsScreenshotManager {
message_loop_runner_->Run();
}
+ bool ScreenshotSetForEntry(NavigationEntryImpl* entry) const {
+ return screenshot_set_.count(entry) > 0;
+ }
+
private:
// Overridden from WebContentsScreenshotManager:
virtual void TakeScreenshotImpl(RenderViewHost* host,
@@ -68,6 +77,7 @@ class ScreenshotTracker : public WebContentsScreenshotManager {
virtual void OnScreenshotSet(NavigationEntryImpl* entry) OVERRIDE {
--waiting_for_screenshots_;
+ screenshot_set_[entry] = true;
WebContentsScreenshotManager::OnScreenshotSet(entry);
if (waiting_for_screenshots_ == 0 && message_loop_runner_.get())
message_loop_runner_->Quit();
@@ -76,10 +86,42 @@ class ScreenshotTracker : public WebContentsScreenshotManager {
RenderViewHost* screenshot_taken_for_;
scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
int waiting_for_screenshots_;
+ std::map<NavigationEntryImpl*, bool> screenshot_set_;
DISALLOW_COPY_AND_ASSIGN(ScreenshotTracker);
};
+class NavigationWatcher : public WebContentsObserver {
+ public:
+ explicit NavigationWatcher(WebContents* contents)
+ : WebContentsObserver(contents),
+ navigated_(false),
+ should_quit_loop_(false) {
+ }
+
+ virtual ~NavigationWatcher() {}
+
+ void WaitUntilNavigationStarts() {
+ if (navigated_)
+ return;
+ should_quit_loop_ = true;
+ base::MessageLoop::current()->Run();
+ }
+
+ private:
+ // Overridden from WebContentsObserver:
+ virtual void AboutToNavigateRenderView(RenderViewHost* host) OVERRIDE {
+ navigated_ = true;
+ if (should_quit_loop_)
+ base::MessageLoop::current()->Quit();
+ }
+
+ bool navigated_;
+ bool should_quit_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(NavigationWatcher);
+};
+
class WebContentsViewAuraTest : public ContentBrowserTest {
public:
WebContentsViewAuraTest()
@@ -89,6 +131,7 @@ class WebContentsViewAuraTest : public ContentBrowserTest {
virtual void SetUp() OVERRIDE {
// TODO(jbauman): Remove this. http://crbug.com/268644
UseRealGLContexts();
+ ContentBrowserTest::SetUp();
}
// Executes the javascript synchronously and makes sure the returned value is
@@ -151,6 +194,8 @@ class WebContentsViewAuraTest : public ContentBrowserTest {
aura::Window* content = web_contents->GetView()->GetContentNativeView();
gfx::Rect bounds = content->GetBoundsInRootWindow();
aura::test::EventGenerator generator(content->GetRootWindow(), content);
+ const int kScrollDurationMs = 20;
+ const int kScrollSteps = 10;
{
// Do a swipe-right now. That should navigate backwards.
@@ -159,8 +204,8 @@ class WebContentsViewAuraTest : public ContentBrowserTest {
generator.GestureScrollSequence(
gfx::Point(bounds.x() + 2, bounds.y() + 10),
gfx::Point(bounds.right() - 10, bounds.y() + 10),
- base::TimeDelta::FromMilliseconds(20),
- 1);
+ base::TimeDelta::FromMilliseconds(kScrollDurationMs),
+ kScrollSteps);
string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
value = content::ExecuteScriptAndGetValue(view_host, "get_current()");
@@ -177,8 +222,8 @@ class WebContentsViewAuraTest : public ContentBrowserTest {
generator.GestureScrollSequence(
gfx::Point(bounds.x() + 2, bounds.y() + 10),
gfx::Point(bounds.right() - 10, bounds.y() + 10),
- base::TimeDelta::FromMilliseconds(20),
- 10);
+ base::TimeDelta::FromMilliseconds(kScrollDurationMs),
+ kScrollSteps);
string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
value = content::ExecuteScriptAndGetValue(view_host, "get_current()");
@@ -195,8 +240,8 @@ class WebContentsViewAuraTest : public ContentBrowserTest {
generator.GestureScrollSequence(
gfx::Point(bounds.right() - 10, bounds.y() + 10),
gfx::Point(bounds.x() + 2, bounds.y() + 10),
- base::TimeDelta::FromMilliseconds(20),
- 10);
+ base::TimeDelta::FromMilliseconds(kScrollDurationMs),
+ kScrollSteps);
string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
value = content::ExecuteScriptAndGetValue(view_host, "get_current()");
@@ -328,8 +373,15 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
// - interactively, when user does an overscroll gesture
// - interactively, when user navigates in history without the overscroll
// gesture.
-IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
- OverscrollScreenshot) {
+IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, OverscrollScreenshot) {
+ // 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
+
ASSERT_NO_FATAL_FAILURE(
StartTestWithPage("files/overscroll_navigation.html"));
WebContentsImpl* web_contents =
@@ -354,11 +406,11 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
entry = NavigationEntryImpl::FromNavigationEntry(
web_contents->GetController().GetEntryAtIndex(1));
- EXPECT_TRUE(entry->screenshot().get());
+ EXPECT_TRUE(screenshot_manager()->ScreenshotSetForEntry(entry));
entry = NavigationEntryImpl::FromNavigationEntry(
web_contents->GetController().GetEntryAtIndex(0));
- EXPECT_TRUE(entry->screenshot().get());
+ EXPECT_TRUE(screenshot_manager()->ScreenshotSetForEntry(entry));
// Navigate again. Index 2 should now have a screenshot.
ExecuteSyncJSFunction(view_host, "navigate_next()");
@@ -367,7 +419,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
entry = NavigationEntryImpl::FromNavigationEntry(
web_contents->GetController().GetEntryAtIndex(2));
- EXPECT_TRUE(entry->screenshot().get());
+ EXPECT_TRUE(screenshot_manager()->ScreenshotSetForEntry(entry));
entry = NavigationEntryImpl::FromNavigationEntry(
web_contents->GetController().GetEntryAtIndex(3));
@@ -392,7 +444,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
screenshot_manager()->WaitUntilScreenshotIsReady();
entry = NavigationEntryImpl::FromNavigationEntry(
web_contents->GetController().GetEntryAtIndex(3));
- EXPECT_TRUE(entry->screenshot().get());
+ EXPECT_TRUE(screenshot_manager()->ScreenshotSetForEntry(entry));
}
// Navigate a couple more times.
@@ -416,7 +468,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
screenshot_manager()->WaitUntilScreenshotIsReady();
entry = NavigationEntryImpl::FromNavigationEntry(
web_contents->GetController().GetEntryAtIndex(4));
- EXPECT_TRUE(entry->screenshot().get());
+ EXPECT_TRUE(screenshot_manager()->ScreenshotSetForEntry(entry));
}
}
@@ -464,15 +516,16 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
EXPECT_NE(old_host, web_contents->GetRenderViewHost())
<< navigations[i].url.spec();
EXPECT_EQ(old_host, screenshot_manager()->screenshot_taken_for());
- screenshot_manager()->Reset();
NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
web_contents->GetController().GetEntryAtOffset(-1));
- EXPECT_TRUE(entry->screenshot().get());
+ EXPECT_TRUE(screenshot_manager()->ScreenshotSetForEntry(entry));
entry = NavigationEntryImpl::FromNavigationEntry(
web_contents->GetController().GetActiveEntry());
+ EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry));
EXPECT_FALSE(entry->screenshot().get());
+ screenshot_manager()->Reset();
}
// Increase the minimum interval between taking screenshots.
@@ -568,6 +621,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
web_contents->GetController().GoBack();
WaitForLoadStop(web_contents);
EXPECT_EQ(1, GetCurrentIndex());
+ EXPECT_EQ(base::ASCIIToUTF16("Title: #1"), web_contents->GetTitle());
EXPECT_TRUE(controller.CanGoBack());
EXPECT_TRUE(controller.CanGoForward());
@@ -579,18 +633,15 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
// right.
string16 expected_title = ASCIIToUTF16("Title: #2");
content::TitleWatcher title_watcher(web_contents, expected_title);
+ NavigationWatcher nav_watcher(web_contents);
generator.GestureScrollSequence(
gfx::Point(bounds.right() - 10, bounds.y() + 10),
gfx::Point(bounds.x() + 2, bounds.y() + 10),
base::TimeDelta::FromMilliseconds(2000),
10);
- // Make sure the GestureEventFilter's debouncing doesn't interfere.
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::MessageLoop::QuitClosure(),
- base::TimeDelta::FromMilliseconds(100));
- base::MessageLoop::current()->Run();
+ nav_watcher.WaitUntilNavigationStarts();
+
generator.GestureScrollSequence(
gfx::Point(bounds.x() + 2, bounds.y() + 10),
gfx::Point(bounds.right() - 10, bounds.y() + 10),
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 6a9459d3e95..d1ab628b33e 100644
--- a/chromium/content/browser/web_contents/web_contents_view_mac.mm
+++ b/chromium/content/browser/web_contents/web_contents_view_mac.mm
@@ -512,6 +512,18 @@ void WebContentsViewMac::CloseTab() {
[dragSource_ moveDragTo:screenPoint];
}
+// Called when a file drag is dropped and the promised files need to be written.
+- (NSArray*)namesOfPromisedFilesDroppedAtDestination:(NSURL*)dropDest {
+ if (![dropDest isFileURL])
+ return nil;
+
+ NSString* fileName = [dragSource_ dragPromisedFileTo:[dropDest path]];
+ if (!fileName)
+ return nil;
+
+ return @[ fileName ];
+}
+
// NSDraggingDestination methods
- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender {
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 6a75e71cab5..0c65b1dc181 100644
--- a/chromium/content/browser/web_contents/web_contents_view_win.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_win.cc
@@ -246,6 +246,7 @@ void WebContentsViewWin::SetOverscrollControllerEnabled(bool enabled) {
void WebContentsViewWin::ShowContextMenu(const ContextMenuParams& params) {
if (delegate_)
delegate_->ShowContextMenu(params);
+ // WARNING: this may have been deleted.
}
void WebContentsViewWin::ShowPopupMenu(const gfx::Rect& bounds,
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 3ca6b48765a..adfe6751fad 100644
--- a/chromium/content/browser/web_contents/web_contents_view_win.h
+++ b/chromium/content/browser/web_contents/web_contents_view_win.h
@@ -13,7 +13,7 @@
#include "content/common/drag_event_source_info.h"
#include "content/port/browser/render_view_host_delegate_view.h"
#include "content/port/browser/web_contents_view_port.h"
-#include "ui/base/win/window_impl.h"
+#include "ui/gfx/win/window_impl.h"
namespace ui {
class HWNDMessageFilter;
@@ -29,7 +29,7 @@ class WebDragDest;
class CONTENT_EXPORT WebContentsViewWin
: public WebContentsViewPort,
public RenderViewHostDelegateView,
- public ui::WindowImpl {
+ public gfx::WindowImpl {
public:
WebContentsViewWin(WebContentsImpl* web_contents,
WebContentsViewDelegate* delegate);
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 0f1d9d57876..0ad27de95c8 100644
--- a/chromium/content/browser/web_contents/web_drag_source_gtk.cc
+++ b/chromium/content/browser/web_contents/web_drag_source_gtk.cc
@@ -24,8 +24,8 @@
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/clipboard/custom_data_helper.h"
#include "ui/base/dragdrop/gtk_dnd_util.h"
-#include "ui/base/gtk/gtk_compat.h"
#include "ui/base/gtk/gtk_screen_util.h"
+#include "ui/gfx/gtk_compat.h"
#include "ui/gfx/gtk_util.h"
using WebKit::WebDragOperation;
diff --git a/chromium/content/browser/web_contents/web_drag_source_mac.h b/chromium/content/browser/web_contents/web_drag_source_mac.h
index 4b18953abf6..f355728a594 100644
--- a/chromium/content/browser/web_contents/web_drag_source_mac.h
+++ b/chromium/content/browser/web_contents/web_drag_source_mac.h
@@ -86,4 +86,10 @@ CONTENT_EXPORT
// Drag moved; hook up to -draggedImage:movedTo:.
- (void)moveDragTo:(NSPoint)screenPoint;
+// Call to drag a promised file to the given path (should be called before
+// -endDragAt:...); hook up to -namesOfPromisedFilesDroppedAtDestination:.
+// Returns the file name (not including path) of the file deposited (or which
+// will be deposited).
+- (NSString*)dragPromisedFileTo:(NSString*)path;
+
@end
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 0b44fd47930..041737935e9 100644
--- a/chromium/content/browser/web_contents/web_drag_source_mac.mm
+++ b/chromium/content/browser/web_contents/web_drag_source_mac.mm
@@ -8,9 +8,7 @@
#include "base/bind.h"
#include "base/files/file_path.h"
-#include "base/mac/mac_logging.h"
#include "base/mac/mac_util.h"
-#include "base/mac/scoped_aedesc.h"
#include "base/pickle.h"
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
@@ -93,121 +91,11 @@ void PromiseWriterHelper(const DropData& drop_data,
drop_data.file_contents.length());
}
-// Returns the drop location from a pasteboard.
-NSString* GetDropLocation(NSPasteboard* pboard) {
- // The API to get the drop location during a callback from
- // kPasteboardTypeFileURLPromise is PasteboardCopyPasteLocation, which takes
- // a PasteboardRef, which isn't bridged with NSPasteboard. Ugh.
-
- PasteboardRef pb_ref = NULL;
- OSStatus status = PasteboardCreate(base::mac::NSToCFCast([pboard name]),
- &pb_ref);
- if (status != noErr || !pb_ref) {
- OSSTATUS_DCHECK(false, status) << "Error finding Carbon pasteboard";
- return nil;
- }
- base::ScopedCFTypeRef<PasteboardRef> pb_ref_scoper(pb_ref);
- PasteboardSynchronize(pb_ref);
-
- CFURLRef drop_url = NULL;
- status = PasteboardCopyPasteLocation(pb_ref, &drop_url);
- if (status != noErr || !drop_url) {
- OSSTATUS_DCHECK(false, status) << "Error finding drop location";
- return nil;
- }
- base::ScopedCFTypeRef<CFURLRef> drop_url_scoper(drop_url);
-
- NSString* drop_path = [base::mac::CFToNSCast(drop_url) path];
- return drop_path;
-}
-
-void SelectFileInFinder(const base::FilePath& file_path) {
- DCHECK([NSThread isMainThread]);
-
- // Create the target of this AppleEvent, the Finder.
- base::mac::ScopedAEDesc<AEAddressDesc> address;
- const OSType finder_creator_code = 'MACS';
- OSErr status = AECreateDesc(typeApplSignature, // type
- &finder_creator_code, // data
- sizeof(finder_creator_code), // dataSize
- address.OutPointer()); // result
- if (status != noErr) {
- OSSTATUS_LOG(WARNING, status) << "Could not create SelectFile() AE target";
- return;
- }
-
- // Build the AppleEvent data structure that instructs Finder to select files.
- base::mac::ScopedAEDesc<AppleEvent> the_event;
- status = AECreateAppleEvent(kAEMiscStandards, // theAEEventClass
- kAESelect, // theAEEventID
- address, // target
- kAutoGenerateReturnID, // returnID
- kAnyTransactionID, // transactionID
- the_event.OutPointer()); // result
- if (status != noErr) {
- OSSTATUS_LOG(WARNING, status) << "Could not create SelectFile() AE event";
- return;
- }
-
- // Create the list of files (only ever one) to select.
- base::mac::ScopedAEDesc<AEDescList> file_list;
- status = AECreateList(NULL, // factoringPtr
- 0, // factoredSize
- false, // isRecord
- file_list.OutPointer()); // resultList
- if (status != noErr) {
- OSSTATUS_LOG(WARNING, status)
- << "Could not create SelectFile() AE file list";
- return;
- }
-
- // Add the single path to the file list.
- NSURL* url = [NSURL fileURLWithPath:SysUTF8ToNSString(file_path.value())];
- base::ScopedCFTypeRef<CFDataRef> url_data(
- CFURLCreateData(kCFAllocatorDefault, base::mac::NSToCFCast(url),
- kCFStringEncodingUTF8, true));
- status = AEPutPtr(file_list.OutPointer(), // theAEDescList
- 0, // index
- typeFileURL, // typeCode
- CFDataGetBytePtr(url_data), // dataPtr
- CFDataGetLength(url_data)); // dataSize
- if (status != noErr) {
- OSSTATUS_LOG(WARNING, status)
- << "Could not add file path to AE list in SelectFile()";
- return;
- }
-
- // Attach the file list to the AppleEvent.
- status = AEPutParamDesc(the_event.OutPointer(), // theAppleEvent
- keyDirectObject, // theAEKeyword
- file_list); // theAEDesc
- if (status != noErr) {
- OSSTATUS_LOG(WARNING, status)
- << "Could not put the AE file list the path in SelectFile()";
- return;
- }
-
- // Send the actual event. Do not care about the reply.
- base::mac::ScopedAEDesc<AppleEvent> reply;
- status = AESend(the_event, // theAppleEvent
- reply.OutPointer(), // reply
- kAENoReply + kAEAlwaysInteract, // sendMode
- kAENormalPriority, // sendPriority
- kAEDefaultTimeout, // timeOutInTicks
- NULL, // idleProc
- NULL); // filterProc
- if (status != noErr) {
- OSSTATUS_LOG(WARNING, status)
- << "Could not send AE to Finder in SelectFile()";
- }
-}
-
} // namespace
@interface WebDragSource(Private)
-- (void)writePromisedFileTo:(NSString*)path;
- (void)fillPasteboard;
- (NSImage*)dragImage;
@@ -282,7 +170,7 @@ void SelectFileInFinder(const base::FilePath& file_path) {
NSURL* url = [NSURL URLWithString:SysUTF8ToNSString(dropData_->url.spec())];
// If NSURL creation failed, check for a badly-escaped JavaScript URL.
// Strip out any existing escapes and then re-escape uniformly.
- if (!url && dropData_->url.SchemeIs(chrome::kJavaScriptScheme)) {
+ if (!url && dropData_->url.SchemeIs(content::kJavaScriptScheme)) {
net::UnescapeRule::Type unescapeRules =
net::UnescapeRule::SPACES |
net::UnescapeRule::URL_SPECIAL_CHARS |
@@ -324,18 +212,6 @@ void SelectFileInFinder(const base::FilePath& file_path) {
[pboard setData:[NSData data]
forType:ui::kChromeDragDummyPboardType];
- // File promise.
- } else if ([type isEqualToString:
- base::mac::CFToNSCast(kPasteboardTypeFileURLPromise)]) {
- NSString* destination = GetDropLocation(pboard);
- if (destination) {
- [self writePromisedFileTo:destination];
-
- // And set some data.
- [pboard setData:[NSData data]
- forType:base::mac::CFToNSCast(kPasteboardTypeFileURLPromise)];
- }
-
// Oops!
} else {
// Unknown drag pasteboard type.
@@ -437,15 +313,11 @@ void SelectFileInFinder(const base::FilePath& file_path) {
}
}
-@end // @implementation WebDragSource
-
-@implementation WebDragSource (Private)
-
-- (void)writePromisedFileTo:(NSString*)path {
+- (NSString*)dragPromisedFileTo:(NSString*)path {
// Be extra paranoid; avoid crashing.
if (!dropData_) {
NOTREACHED() << "No drag-and-drop data available for promised file.";
- return;
+ return nil;
}
base::FilePath filePath(SysNSStringToUTF8(path));
@@ -458,14 +330,15 @@ void SelectFileInFinder(const base::FilePath& file_path) {
scoped_ptr<FileStream> fileStream(content::CreateFileStreamForDrop(
&filePath, content::GetContentClient()->browser()->GetNetLog()));
if (!fileStream)
- return;
+ return nil;
if (downloadURL_.is_valid()) {
scoped_refptr<DragDownloadFile> dragFileDownloader(new DragDownloadFile(
filePath,
fileStream.Pass(),
downloadURL_,
- content::Referrer(contents_->GetURL(), dropData_->referrer_policy),
+ content::Referrer(contents_->GetLastCommittedURL(),
+ dropData_->referrer_policy),
contents_->GetEncoding(),
contents_));
@@ -480,18 +353,26 @@ void SelectFileInFinder(const base::FilePath& file_path) {
*dropData_,
base::Passed(&fileStream)));
}
- SelectFileInFinder(filePath);
+
+ // The DragDownloadFile constructor may have altered the value of |filePath|
+ // if, say, an existing file at the drop site has the same name. Return the
+ // actual name that was used to write the file.
+ return SysUTF8ToNSString(filePath.BaseName().value());
}
+@end // @implementation WebDragSource
+
+@implementation WebDragSource (Private)
+
- (void)fillPasteboard {
DCHECK(pasteboard_.get());
- [pasteboard_ declareTypes:@[ui::kChromeDragDummyPboardType]
+ [pasteboard_ declareTypes:@[ ui::kChromeDragDummyPboardType ]
owner:contentsView_];
// URL (and title).
if (dropData_->url.is_valid()) {
- [pasteboard_ addTypes:@[NSURLPboardType, kNSURLTitlePboardType]
+ [pasteboard_ addTypes:@[ NSURLPboardType, kNSURLTitlePboardType ]
owner:contentsView_];
}
@@ -533,18 +414,33 @@ void SelectFileInFinder(const base::FilePath& file_path) {
fileUTI_.reset(UTTypeCreatePreferredIdentifierForTag(
kUTTagClassMIMEType, mimeTypeCF.get(), NULL));
- NSArray* types =
- @[base::mac::CFToNSCast(kPasteboardTypeFileURLPromise),
- base::mac::CFToNSCast(kPasteboardTypeFilePromiseContent)];
- [pasteboard_ addTypes:types owner:contentsView_];
-
- [pasteboard_ setPropertyList:@[base::mac::CFToNSCast(fileUTI_.get())]
- forType:base::mac::CFToNSCast(kPasteboardTypeFilePromiseContent)];
-
- if (!dropData_->file_contents.empty()) {
- NSArray* types = @[base::mac::CFToNSCast(fileUTI_.get())];
- [pasteboard_ addTypes:types owner:contentsView_];
- }
+ // File (HFS) promise.
+ // There are two ways to drag/drop files. NSFilesPromisePboardType is the
+ // deprecated way, and kPasteboardTypeFilePromiseContent is the way that
+ // does not work. kPasteboardTypeFilePromiseContent is thoroughly broken:
+ // * API: There is no good way to get the location for the drop.
+ // <http://lists.apple.com/archives/cocoa-dev/2012/Feb/msg00706.html>
+ // <rdar://14943849> <http://openradar.me/14943849>
+ // * Behavior: A file dropped in the Finder is not selected. This can be
+ // worked around by selecting the file in the Finder using AppleEvents,
+ // but the drop target window will come to the front of the Finder's
+ // window list (unlike the previous behavior). <http://crbug.com/278515>
+ // <rdar://14943865> <http://openradar.me/14943865>
+ // * Behavior: Files dragged over app icons in the dock do not highlight
+ // the dock icons, and the dock icons do not accept the drop.
+ // <http://crbug.com/282916> <rdar://14943872>
+ // <http://openradar.me/14943872>
+ // * Behavior: A file dropped onto the desktop is positioned at the upper
+ // right of the desktop rather than at the position at which it was
+ // dropped. <http://crbug.com/284942> <rdar://14943881>
+ // <http://openradar.me/14943881>
+ NSArray* fileUTIList = @[ base::mac::CFToNSCast(fileUTI_.get()) ];
+ [pasteboard_ addTypes:@[ NSFilesPromisePboardType ] owner:contentsView_];
+ [pasteboard_ setPropertyList:fileUTIList
+ forType:NSFilesPromisePboardType];
+
+ if (!dropData_->file_contents.empty())
+ [pasteboard_ addTypes:fileUTIList owner:contentsView_];
}
}
@@ -562,21 +458,21 @@ void SelectFileInFinder(const base::FilePath& file_path) {
UTTypeConformsTo(fileUTI_.get(), kUTTypeImage);
if (hasHTMLData) {
if (hasImageData) {
- [pasteboard_ addTypes:@[ui::kChromeDragImageHTMLPboardType]
+ [pasteboard_ addTypes:@[ ui::kChromeDragImageHTMLPboardType ]
owner:contentsView_];
} else {
- [pasteboard_ addTypes:@[NSHTMLPboardType] owner:contentsView_];
+ [pasteboard_ addTypes:@[ NSHTMLPboardType ] owner:contentsView_];
}
}
// Plain text.
if (!dropData_->text.string().empty()) {
- [pasteboard_ addTypes:@[NSStringPboardType]
+ [pasteboard_ addTypes:@[ NSStringPboardType ]
owner:contentsView_];
}
if (!dropData_->custom_data.empty()) {
- [pasteboard_ addTypes:@[ui::kWebCustomDataPboardType]
+ [pasteboard_ addTypes:@[ ui::kWebCustomDataPboardType ]
owner:contentsView_];
}
}
diff --git a/chromium/content/browser/webkit_browsertest.cc b/chromium/content/browser/webkit_browsertest.cc
index 24c24a60caa..5394f5bcc55 100644
--- a/chromium/content/browser/webkit_browsertest.cc
+++ b/chromium/content/browser/webkit_browsertest.cc
@@ -4,7 +4,7 @@
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/web_contents.h"
-#include "content/shell/shell.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/net/url_request_abort_on_end_job.h"
diff --git a/chromium/content/browser/webui/shared_resources_data_source.cc b/chromium/content/browser/webui/shared_resources_data_source.cc
index 23cdc3d23a3..45ddc793a65 100644
--- a/chromium/content/browser/webui/shared_resources_data_source.cc
+++ b/chromium/content/browser/webui/shared_resources_data_source.cc
@@ -6,6 +6,7 @@
#include "base/logging.h"
#include "base/memory/ref_counted_memory.h"
+#include "base/strings/string_util.h"
#include "base/threading/thread_restrictions.h"
#include "content/public/common/content_client.h"
#include "content/public/common/url_constants.h"
@@ -14,10 +15,37 @@
namespace {
+const char kAppImagesPath[] = "images/apps/";
+const char kAppImagesPath2x[] = "images/2x/apps/";
+
+const char kReplacement[] = "../../resources/default_100_percent/common/";
+const char kReplacement2x[] = "../../resources/default_200_percent/common/";
+
+// This entire method is a hack introduced to be able to handle apps images
+// that exist in the ui/resources directory. From JS/CSS, we still load the
+// image as if it were chrome://resources/images/apps/myappimage.png, if that
+// path doesn't exist, we check to see if it that image exists in the relative
+// path to ui/resources instead.
+// TODO(rkc): Once we have a separate source for apps, remove this code.
+bool AppsRelativePathMatch(const std::string& path,
+ const std::string& compareto) {
+ if (StartsWithASCII(path, kAppImagesPath, false)) {
+ if (compareto ==
+ (kReplacement + path.substr(arraysize(kAppImagesPath) - 1)))
+ return true;
+ } else if (StartsWithASCII(path, kAppImagesPath2x, false)) {
+ if (compareto ==
+ (kReplacement2x + path.substr(arraysize(kAppImagesPath2x) - 1)))
+ return true;
+ }
+ return false;
+}
+
int PathToIDR(const std::string& path) {
int idr = -1;
for (size_t i = 0; i < kWebuiResourcesSize; ++i) {
- if (kWebuiResources[i].name == path) {
+ if ((path == kWebuiResources[i].name) ||
+ AppsRelativePathMatch(path, kWebuiResources[i].name)) {
idr = kWebuiResources[i].value;
break;
}
diff --git a/chromium/content/browser/webui/url_data_manager_backend.cc b/chromium/content/browser/webui/url_data_manager_backend.cc
index 7c4c77b9bb9..1bcbdb76e9e 100644
--- a/chromium/content/browser/webui/url_data_manager_backend.cc
+++ b/chromium/content/browser/webui/url_data_manager_backend.cc
@@ -388,7 +388,7 @@ class ChromeProtocolHandler
// Next check for chrome://blob-internals/, which uses its own job type.
if (ViewBlobInternalsJobFactory::IsSupportedURL(request->url())) {
return ViewBlobInternalsJobFactory::CreateJobForRequest(
- request, network_delegate, blob_storage_context_->controller());
+ request, network_delegate, blob_storage_context_->context());
}
#if defined(USE_TCMALLOC)
diff --git a/chromium/content/browser/webui/web_ui_controller_factory_registry.cc b/chromium/content/browser/webui/web_ui_controller_factory_registry.cc
index 675bd8f8d0b..ede404d9939 100644
--- a/chromium/content/browser/webui/web_ui_controller_factory_registry.cc
+++ b/chromium/content/browser/webui/web_ui_controller_factory_registry.cc
@@ -82,7 +82,7 @@ bool WebUIControllerFactoryRegistry::IsURLAcceptableForWebUI(
bool data_urls_allowed) const {
return UseWebUIForURL(browser_context, url) ||
// javascript: URLs are allowed to run in Web UI pages.
- url.SchemeIs(chrome::kJavaScriptScheme) ||
+ url.SchemeIs(kJavaScriptScheme) ||
// It's possible to load about:blank in a Web UI renderer.
// See http://crbug.com/42547
url.spec() == kAboutBlankURL ||
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 b564e57599b..9d0d17128a6 100644
--- a/chromium/content/browser/webui/web_ui_data_source_impl.cc
+++ b/chromium/content/browser/webui/web_ui_data_source_impl.cc
@@ -49,6 +49,9 @@ class WebUIDataSourceImpl::InternalDataSource : public URLDataSource {
return parent_->StartDataRequest(path, render_process_id, render_view_id,
callback);
}
+ virtual bool ShouldReplaceExistingSource() const OVERRIDE {
+ return parent_->replace_existing_source_;
+ }
virtual bool ShouldAddContentSecurityPolicy() const OVERRIDE {
return parent_->add_csp_;
}
@@ -81,7 +84,8 @@ WebUIDataSourceImpl::WebUIDataSourceImpl(const std::string& source_name)
object_src_set_(false),
frame_src_set_(false),
deny_xframe_options_(true),
- disable_set_font_strings_(false) {
+ disable_set_font_strings_(false),
+ replace_existing_source_(true) {
}
WebUIDataSourceImpl::~WebUIDataSourceImpl() {
@@ -134,6 +138,10 @@ void WebUIDataSourceImpl::SetRequestFilter(
filter_callback_ = callback;
}
+void WebUIDataSourceImpl::DisableReplaceExistingSource() {
+ replace_existing_source_ = false;
+}
+
void WebUIDataSourceImpl::DisableContentSecurityPolicy() {
add_csp_ = false;
}
@@ -168,6 +176,9 @@ std::string WebUIDataSourceImpl::GetMimeType(const std::string& path) const {
if (EndsWith(path, ".pdf", false))
return "application/pdf";
+ if (EndsWith(path, ".svg", false))
+ return "image/svg+xml";
+
return "text/html";
}
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 0b6f8a355d3..1f8100469e7 100644
--- a/chromium/content/browser/webui/web_ui_data_source_impl.h
+++ b/chromium/content/browser/webui/web_ui_data_source_impl.h
@@ -42,6 +42,7 @@ class CONTENT_EXPORT WebUIDataSourceImpl
virtual void SetDefaultResource(int resource_id) OVERRIDE;
virtual void SetRequestFilter(
const WebUIDataSource::HandleRequestCallback& callback) OVERRIDE;
+ virtual void DisableReplaceExistingSource() OVERRIDE;
virtual void DisableContentSecurityPolicy() OVERRIDE;
virtual void OverrideContentSecurityPolicyObjectSrc(
const std::string& data) OVERRIDE;
@@ -99,6 +100,7 @@ class CONTENT_EXPORT WebUIDataSourceImpl
std::string frame_src_;
bool deny_xframe_options_;
bool disable_set_font_strings_;
+ bool replace_existing_source_;
DISALLOW_COPY_AND_ASSIGN(WebUIDataSourceImpl);
};
diff --git a/chromium/content/browser/worker_host/message_port_service.cc b/chromium/content/browser/worker_host/message_port_service.cc
index d0563f0c23a..b413c1f8c60 100644
--- a/chromium/content/browser/worker_host/message_port_service.cc
+++ b/chromium/content/browser/worker_host/message_port_service.cc
@@ -124,10 +124,8 @@ void MessagePortService::PostMessageTo(
MessagePort& entangled_port = message_ports_[message_port_id];
std::vector<MessagePort*> sent_ports(sent_message_port_ids.size());
- for (size_t i = 0; i < sent_message_port_ids.size(); ++i) {
+ for (size_t i = 0; i < sent_message_port_ids.size(); ++i)
sent_ports[i] = &message_ports_[sent_message_port_ids[i]];
- sent_ports[i]->queue_messages = true;
- }
if (entangled_port.queue_messages) {
entangled_port.queued_messages.push_back(
diff --git a/chromium/content/browser/worker_host/message_port_service.h b/chromium/content/browser/worker_host/message_port_service.h
index e6bf71767bb..30645c79b65 100644
--- a/chromium/content/browser/worker_host/message_port_service.h
+++ b/chromium/content/browser/worker_host/message_port_service.h
@@ -72,6 +72,13 @@ class MessagePortService {
// The globally unique id of the entangled message port.
int entangled_message_port_id;
// If true, all messages to this message port are queued and not delivered.
+ // This is needed so that when a message port is sent between processes all
+ // pending message get transferred. There are two possibilities for pending
+ // messages: either they are already received by the child process, or they're
+ // 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.
bool queue_messages;
QueuedMessages queued_messages;
};
diff --git a/chromium/content/browser/worker_host/worker_process_host.cc b/chromium/content/browser/worker_host/worker_process_host.cc
index fa37574a772..a228f9cf0eb 100644
--- a/chromium/content/browser/worker_host/worker_process_host.cc
+++ b/chromium/content/browser/worker_host/worker_process_host.cc
@@ -24,6 +24,7 @@
#include "content/browser/devtools/worker_devtools_message_filter.h"
#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/mime_registry_message_filter.h"
#include "content/browser/quota_dispatcher_host.h"
#include "content/browser/renderer_host/database_message_filter.h"
@@ -75,31 +76,6 @@ class WorkerSandboxedProcessLauncherDelegate
};
#endif // OS_WIN
-// Helper class that we pass to SocketStreamDispatcherHost so that it can find
-// the right net::URLRequestContext for a request.
-class URLRequestContextSelector
- : public ResourceMessageFilter::URLRequestContextSelector {
- public:
- explicit URLRequestContextSelector(
- net::URLRequestContextGetter* url_request_context,
- net::URLRequestContextGetter* media_url_request_context)
- : url_request_context_(url_request_context),
- media_url_request_context_(media_url_request_context) {
- }
- virtual ~URLRequestContextSelector() {}
-
- virtual net::URLRequestContext* GetRequestContext(
- ResourceType::Type resource_type) OVERRIDE {
- if (resource_type == ResourceType::MEDIA)
- return media_url_request_context_->GetURLRequestContext();
- return url_request_context_->GetURLRequestContext();
- }
-
- private:
- net::URLRequestContextGetter* url_request_context_;
- net::URLRequestContextGetter* media_url_request_context_;
-};
-
} // namespace
// Notifies RenderViewHost that one or more worker objects crashed.
@@ -215,7 +191,7 @@ bool WorkerProcessHost::Init(int render_process_id) {
new WorkerSandboxedProcessLauncherDelegate,
#elif defined(OS_POSIX)
use_zygote,
- base::EnvironmentVector(),
+ base::EnvironmentMap(),
#endif
cmd_line);
@@ -234,16 +210,17 @@ void WorkerProcessHost::CreateMessageFilters(int render_process_id) {
net::URLRequestContextGetter* url_request_context =
partition_.url_request_context();
- net::URLRequestContextGetter* media_url_request_context =
- partition_.url_request_context();
+
+ ResourceMessageFilter::GetContextsCallback get_contexts_callback(
+ base::Bind(&WorkerProcessHost::GetContexts,
+ base::Unretained(this)));
ResourceMessageFilter* resource_message_filter = new ResourceMessageFilter(
- process_->GetData().id, PROCESS_TYPE_WORKER, resource_context_,
+ process_->GetData().id, PROCESS_TYPE_WORKER,
partition_.appcache_service(),
blob_storage_context,
partition_.filesystem_context(),
- new URLRequestContextSelector(url_request_context,
- media_url_request_context));
+ get_contexts_callback);
process_->GetHost()->AddFilter(resource_message_filter);
worker_message_filter_ = new WorkerMessageFilter(
@@ -269,11 +246,15 @@ void WorkerProcessHost::CreateMessageFilters(int render_process_id) {
partition_.quota_manager(),
GetContentClient()->browser()->CreateQuotaPermissionContext()));
+ SocketStreamDispatcherHost::GetRequestContextCallback
+ request_context_callback(
+ base::Bind(&WorkerProcessHost::GetRequestContext,
+ base::Unretained(this)));
+
SocketStreamDispatcherHost* socket_stream_dispatcher_host =
new SocketStreamDispatcherHost(
render_process_id,
- new URLRequestContextSelector(url_request_context,
- media_url_request_context),
+ request_context_callback,
resource_context_);
socket_stream_dispatcher_host_ = socket_stream_dispatcher_host;
process_->GetHost()->AddFilter(socket_stream_dispatcher_host);
@@ -588,6 +569,18 @@ std::vector<std::pair<int, int> > WorkerProcessHost::GetRenderViewIDsForWorker(
return result;
}
+void WorkerProcessHost::GetContexts(const ResourceHostMsg_Request& request,
+ ResourceContext** resource_context,
+ net::URLRequestContext** request_context) {
+ *resource_context = resource_context_;
+ *request_context = partition_.url_request_context()->GetURLRequestContext();
+}
+
+net::URLRequestContext* WorkerProcessHost::GetRequestContext(
+ ResourceType::Type resource_type) {
+ return partition_.url_request_context()->GetURLRequestContext();
+}
+
WorkerProcessHost::WorkerInstance::WorkerInstance(
const GURL& url,
const string16& name,
diff --git a/chromium/content/browser/worker_host/worker_process_host.h b/chromium/content/browser/worker_host/worker_process_host.h
index 226d3454f55..7bc6884e64a 100644
--- a/chromium/content/browser/worker_host/worker_process_host.h
+++ b/chromium/content/browser/worker_host/worker_process_host.h
@@ -20,11 +20,18 @@
#include "content/public/common/process_type.h"
#include "ipc/ipc_sender.h"
#include "url/gurl.h"
+#include "webkit/common/resource_type.h"
+
+struct ResourceHostMsg_Request;
namespace fileapi {
class FileSystemContext;
} // namespace fileapi
+namespace net {
+class URLRequestContext;
+}
+
namespace webkit_database {
class DatabaseTracker;
} // namespace webkit_database
@@ -218,6 +225,12 @@ class WorkerProcessHost : public BrowserChildProcessHostDelegate,
// given worker.
std::vector<std::pair<int, int> > GetRenderViewIDsForWorker(int route_id);
+ // Callbacks for ResourceMessageFilter and SocketStreamDispatcherHost.
+ void GetContexts(const ResourceHostMsg_Request& request,
+ ResourceContext** resource_context,
+ net::URLRequestContext** request_context);
+ net::URLRequestContext* GetRequestContext(ResourceType::Type resource_type);
+
Instances instances_;
ResourceContext* const resource_context_;
diff --git a/chromium/content/browser/worker_host/worker_service_impl.cc b/chromium/content/browser/worker_host/worker_service_impl.cc
index 5fb8e62bedb..d2ab272922d 100644
--- a/chromium/content/browser/worker_host/worker_service_impl.cc
+++ b/chromium/content/browser/worker_host/worker_service_impl.cc
@@ -21,6 +21,7 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/render_widget_host_iterator.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/web_contents.h"
@@ -110,16 +111,17 @@ void WorkerPrioritySetter::GatherVisibleIDsAndUpdateWorkerPriorities() {
new std::set<std::pair<int, int> >();
// Gather up all the visible renderer process/view pairs
- RenderWidgetHost::List widgets = RenderWidgetHost::GetRenderWidgetHosts();
- for (size_t i = 0; i < widgets.size(); ++i) {
- if (widgets[i]->GetProcess()->VisibleWidgetCount() == 0)
+ scoped_ptr<RenderWidgetHostIterator> widgets(
+ RenderWidgetHost::GetRenderWidgetHosts());
+ while (RenderWidgetHost* widget = widgets->GetNextHost()) {
+ if (widget->GetProcess()->VisibleWidgetCount() == 0)
continue;
- RenderWidgetHostView* render_view = widgets[i]->GetView();
+ RenderWidgetHostView* render_view = widget->GetView();
if (render_view && render_view->IsShowing()) {
visible_renderer_ids->insert(
- std::pair<int, int>(widgets[i]->GetProcess()->GetID(),
- widgets[i]->GetRoutingID()));
+ std::pair<int, int>(widget->GetProcess()->GetID(),
+ widget->GetRoutingID()));
}
}
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 bb84e62ce3a..fea43b50b17 100644
--- a/chromium/content/browser/zygote_host/zygote_host_impl_linux.cc
+++ b/chromium/content/browser/zygote_host/zygote_host_impl_linux.cc
@@ -29,6 +29,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "content/browser/renderer_host/render_sandbox_host_linux.h"
+#include "content/common/child_process_sandbox_support_impl_linux.h"
#include "content/common/zygote_commands_linux.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_switches.h"
@@ -36,6 +37,7 @@
#include "sandbox/linux/suid/client/setuid_sandbox_client.h"
#include "sandbox/linux/suid/common/sandbox.h"
#include "ui/base/ui_base_switches.h"
+#include "ui/gfx/switches.h"
#if defined(USE_TCMALLOC)
#include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h"
@@ -149,7 +151,7 @@ void ZygoteHostImpl::Init(const std::string& sandbox_cmd) {
// Start up the sandbox host process and get the file descriptor for the
// renderers to talk to it.
const int sfd = RenderSandboxHostLinux::GetInstance()->GetRendererSocket();
- fds_to_map.push_back(std::make_pair(sfd, kZygoteRendererSocketFd));
+ fds_to_map.push_back(std::make_pair(sfd, GetSandboxFD()));
int dummy_fd = -1;
if (using_suid_sandbox_) {
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 9027fe706e3..6a1aca5ba79 100644
--- a/chromium/content/browser/zygote_host/zygote_host_impl_linux.h
+++ b/chromium/content/browser/zygote_host/zygote_host_impl_linux.h
@@ -40,7 +40,11 @@ class CONTENT_EXPORT ZygoteHostImpl : public ZygoteHost {
// Unfortunately the Zygote can not accurately figure out if a process
// is already dead without waiting synchronously for it.
// |known_dead| should be set to true when we already know that the process
- // is dead.
+ // is dead. When |known_dead| is false, processes could be seen as
+ // still running, even when they're not. When |known_dead| is true, the
+ // process will be SIGKILL-ed first (which should have no effect if it was
+ // really dead). This is to prevent a waiting waitpid() from blocking in
+ // a single-threaded Zygote. See crbug.com/157458.
base::TerminationStatus GetTerminationStatus(base::ProcessHandle handle,
bool known_dead,
int* exit_code);